What we’re building
Our signup radar will:- Take an email address as input
- Use Linkup API to search for information about the person
- Return structured data about the person (name, position, company, LinkedIn URL, etc.)
Prerequisites
- A Linkup API key
- Python or Node.js installed
Get your API key
Create a Linkup account for free to get your API key.
Set Up the Client
from linkup import LinkupClient
client = LinkupClient(api_key="<YOUR_LINKUP_API_KEY>")
import { LinkupClient } from 'linkup-sdk';
const client = new LinkupClient({
apiKey: '<YOUR_LINKUP_API_KEY>',
});
Define the Structured Output Schema
The key to our signup radar is using Linkup’s structured output feature. We need to define a schema that specifies what information we want to extract.
import json
schema = {
"type": "object",
"properties": {
"fullName": {
"type": "string",
"description": "The full name of the person"
},
"company": {
"type": "string",
"description": "The company the person works for"
},
"position": {
"type": "string",
"description": "The job title or position of the person"
},
"linkedInUrl": {
"type": "string",
"description": "The LinkedIn profile URL of the person"
},
"companyWebsite": {
"type": "string",
"description": "The website of the company"
},
"additionalInfo": {
"type": "string",
"description": "Any additional relevant information about the person"
}
},
"required": ["fullName", "company"]
}
schema_str = json.dumps(schema)
const schema = {
type: "object",
properties: {
fullName: {
type: "string",
description: "The full name of the person"
},
company: {
type: "string",
description: "The company the person works for"
},
position: {
type: "string",
description: "The job title or position of the person"
},
linkedInUrl: {
type: "string",
description: "The LinkedIn profile URL of the person"
},
companyWebsite: {
type: "string",
description: "The website of the company"
},
additionalInfo: {
type: "string",
description: "Any additional relevant information about the person"
}
},
required: ["fullName", "company"]
};
Create the Signup Radar Function
def signup_radar(email):
# Extract name and domain
name_part = email.split('@')[0]
domain = email.split('@')[1]
# Format name for searching (convert saksena to Saksena)
formatted_name = name_part.capitalize()
# Determine company from domain (if not common email provider)
company_hint = ""
common_domains = ["gmail.com", "hotmail.com", "outlook.com", "yahoo.com", "icloud.com"]
if domain not in common_domains:
company_hint = domain.split('.')[0]
# Create search query
if company_hint:
query = f"Find the LinkedIn profile URL for {formatted_name} who works at {company_hint}. Return their full name, current position, and company information."
else:
query = f"Find the LinkedIn profile URL for someone with the email username {formatted_name}. Return their full name, current position, and company information."
# Call Linkup API
response = client.search(
query=query,
depth="deep", # Use deep for more thorough results
output_type="structured",
structured_output_schema=schema_str
)
return response
# Example usage
from pprint import pprint
result = signup_radar("philippe@linkup.so")
pprint(result)
async function signupRadar(email) {
// Extract name and domain
const [namePart, domain] = email.split('@');
// Format name for searching
const formattedName = namePart.charAt(0).toUpperCase() + namePart.slice(1);
// Determine company from domain (if not common email provider)
let companyHint = "";
const commonDomains = ["gmail.com", "hotmail.com", "outlook.com", "yahoo.com", "icloud.com"];
if (!commonDomains.includes(domain)) {
companyHint = domain.split('.')[0];
}
// Create search query
let query;
if (companyHint) {
query = `Find the LinkedIn profile URL for ${formattedName} who works at ${companyHint}. Return their full name, current position, and company information.`;
} else {
query = `Find the LinkedIn profile URL for someone with the email username ${formattedName}. Return their full name, current position, company, and LinkedIn URL.`;
}
// Call Linkup API
const response = await client.search({
query: query,
depth: "deep", // Use deep for more thorough results
outputType: "structured",
structuredOutputSchema: schema
});
return response;
}
// Example usage
signupRadar("philippe@linkup.so").then(console.log);
Enhance Query Generation
Let’s improve our query to get better results:
def generate_query(email):
name_part = email.split('@')[0]
domain = email.split('@')[1]
# Handle different name formats (snake_case, dot.case, etc.)
if "_" in name_part:
name_parts = name_part.split("_")
formatted_name = " ".join(part.capitalize() for part in name_parts)
elif "." in name_part:
name_parts = name_part.split(".")
formatted_name = " ".join(part.capitalize() for part in name_parts)
else:
formatted_name = name_part.capitalize()
# Determine company from domain
common_domains = ["gmail.com", "hotmail.com", "outlook.com", "yahoo.com", "icloud.com"]
if domain not in common_domains:
company = domain.split('.')[0].capitalize()
return f"Find the LinkedIn profile URL for this person: {formatted_name} at {company}. If the domain of the email address ({domain}) is not a common email provider, it is probably the name of the company this person works for and {domain} is probably the company website, so search specifically for someone with that name at this company. Return their full name, position, company details, LinkedIn URL, as well as any relevant information you can find about them."
else:
return f"Find the LinkedIn profile URL for this person with email username {formatted_name}. Return their full name, current position, company, and LinkedIn URL."
function generateQuery(email) {
const [namePart, domain] = email.split('@');
// Handle different name formats (snake_case, dot.case, etc.)
let formattedName;
if (namePart.includes("_")) {
formattedName = namePart.split("_")
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
.join(" ");
} else if (namePart.includes(".")) {
formattedName = namePart.split(".")
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
.join(" ");
} else {
formattedName = namePart.charAt(0).toUpperCase() + namePart.slice(1);
}
// Determine company from domain
const commonDomains = ["gmail.com", "hotmail.com", "outlook.com", "yahoo.com", "icloud.com"];
if (!commonDomains.includes(domain)) {
const company = domain.split('.')[0].charAt(0).toUpperCase() + domain.split('.')[0].slice(1);
return `Find the LinkedIn profile URL for this person: ${formattedName} at ${company}. If the domain of the email address (${domain}) is not a common email provider, it is probably the name of the company this person works for and ${domain} is probably the company website, so search specifically for someone with that name at this company. Return their full name, position, company details, and LinkedIn URL, as well as any relevant information you can find about them.`;
} else {
return `Find the LinkedIn profile URL for this person with email username ${formattedName}. Return their full name, current position, company, and LinkedIn URL.`;
}
}
Put It All Together
Here’s the complete implementation:
from linkup import LinkupClient
import json
from pprint import pprint
class SignupRadar:
def __init__(self, api_key):
self.client = LinkupClient(api_key=api_key)
self.schema = {
"type": "object",
"properties": {
"fullName": {
"type": "string",
"description": "The full name of the person"
},
"company": {
"type": "string",
"description": "The company the person works for"
},
"position": {
"type": "string",
"description": "The job title or position of the person"
},
"linkedInUrl": {
"type": "string",
"description": "The LinkedIn profile URL of the person"
},
"companyWebsite": {
"type": "string",
"description": "The website of the company"
},
"additionalInfo": {
"type": "string",
"description": "Any additional relevant information about the person"
}
},
"required": ["fullName", "company"]
}
self.schema_str = json.dumps(self.schema)
def generate_query(self, email):
name_part = email.split('@')[0]
domain = email.split('@')[1]
# Handle different name formats (snake_case, dot.case, etc.)
if "_" in name_part:
name_parts = name_part.split("_")
formatted_name = " ".join(part.capitalize() for part in name_parts)
elif "." in name_part:
name_parts = name_part.split(".")
formatted_name = " ".join(part.capitalize() for part in name_parts)
else:
formatted_name = name_part.capitalize()
# Determine company from domain
common_domains = ["gmail.com", "hotmail.com", "outlook.com", "yahoo.com", "icloud.com"]
if domain not in common_domains:
company = domain.split('.')[0].capitalize()
return f"Find the LinkedIn profile URL for this person: {formatted_name} at {company}. If the domain of the email address ({domain}) is not a common email provider, it is probably the name of the company this person works for and {domain} is probably the company website, so search specifically for someone with that name at this company. Return their full name, position, company details, LinkedIn URL, as well as any relevant information you can find about them."
else:
return f"Find the LinkedIn profile URL for this person with email username {formatted_name}. Return their full name, current position, company, and LinkedIn URL."
def lookup(self, email):
query = self.generate_query(email)
response = self.client.search(
query=query,
depth="deep", # Use deep for more thorough results
output_type="structured",
structured_output_schema=self.schema_str
)
return response
# Example usage
if __name__ == "__main__":
radar = SignupRadar(api_key="<YOUR_LINKUP_API_KEY>")
# Example emails
emails = [
"philippe@linkup.so",
"boris@linkup.so"
]
for email in emails:
print(f"\nLooking up: {email}")
result = radar.lookup(email)
pprint(result)
import { LinkupClient } from 'linkup-sdk';
class SignupRadar {
constructor(apiKey) {
this.client = new LinkupClient({
apiKey: apiKey,
});
this.schema = {
type: "object",
properties: {
fullName: {
type: "string",
description: "The full name of the person"
},
company: {
type: "string",
description: "The company the person works for"
},
position: {
type: "string",
description: "The job title or position of the person"
},
linkedInUrl: {
type: "string",
description: "The LinkedIn profile URL of the person"
},
companyWebsite: {
type: "string",
description: "The website of the company"
},
additionalInfo: {
type: "string",
description: "Any additional relevant information about the person"
}
},
required: ["fullName", "company"]
};
}
generateQuery(email) {
const [namePart, domain] = email.split('@');
// Handle different name formats (snake_case, dot.case, etc.)
let formattedName;
if (namePart.includes("_")) {
formattedName = namePart.split("_")
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
.join(" ");
} else if (namePart.includes(".")) {
formattedName = namePart.split(".")
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
.join(" ");
} else {
formattedName = namePart.charAt(0).toUpperCase() + namePart.slice(1);
}
// Determine company from domain
const commonDomains = ["gmail.com", "hotmail.com", "outlook.com", "yahoo.com", "icloud.com"];
if (!commonDomains.includes(domain)) {
const company = domain.split('.')[0].charAt(0).toUpperCase() + domain.split('.')[0].slice(1);
return `Find the LinkedIn profile URL for this person: ${formattedName} at ${company}. If the domain of the email address (${domain}) is not a common email provider, it is probably the name of the company this person works for and ${domain} is probably the company website, so search specifically for someone with that name at this company. Return their full name, position, company details, and LinkedIn URL, as well as any relevant information you can find about them.`;
} else {
return `Find the LinkedIn profile URL for this person with email username ${formattedName}. Return their full name, current position, company, and LinkedIn URL.`;
}
}
async lookup(email) {
const query = this.generateQuery(email);
const response = await this.client.search({
query: query,
depth: "deep", // Use deep for more thorough results
outputType: "structured",
structuredOutputSchema: this.schema
});
return response;
}
}
// Example usage
async function main() {
const radar = new SignupRadar('<YOUR_LINKUP_API_KEY>');
// Example emails
const emails = [
"philippe@linkup.so",
"boris@linkup.so"
];
for (const email of emails) {
console.log(`\nLooking up: ${email}`);
const result = await radar.lookup(email);
console.log(JSON.stringify(result, null, 2));
}
}
main().catch(console.error);
How it works
- Email analysis: the tool parses the email to extract the username and domain.
- Query generation: it creates a smart search query based on the email components:
- Formats the username to handle common patterns (first.last, first_last)
- Uses the domain as a company hint if it’s not a common email provider
- Structured output: uses Linkup’s structured output feature with a custom schema to ensure consistent, well-formatted results.
- Deep search: uses the
"deep"depthfor more comprehensive results.
Test examples
Try the signup radar with these email examples:Advanced enhancements
For a production version, consider adding:- Other relevant information on your users you receive in the sign up form. These should be added to the prompt
- Better manage ambiguity when multiple people could own the same email. Change the prompt and the structured output format to allow for multiple potential people
- Error handling for invalid emails or API failures
- Rate limiting to manage API usage
- Async batch processing for multiple emails
Conclusion
You’ve now built a “signup radar” using the Linkup API that extracts structured information about users from just their email address. Structured output gives you consistent, well-formatted data ready to be ingested into your systems.Need help? Email
support@linkup.so, ping us on Discord, or talk to us.