Skip to main content

Email Lead Capture

Extract lead information from inbound emails including sender details, inquiry type, and topics of interest. This recipe uses the text input method, which lets you send raw email body text directly to the API without a file upload.

Workflow Fields

We recommend creating this workflow in the anyformat platform where you can test with sample emails and iterate on field descriptions. Copy the workflow ID to use with the API.
FieldTypeDescription
sender_namestringName of the person who sent the email
sender_emailstringEmail address of the sender
company_namestringCompany or organization the sender represents
inquiry_typeenumCategory of the inquiry
urgencyenumHow urgent the request seems
topicsmulti_selectProducts or areas mentioned
summarystringBrief summary of the email

Field Configuration

{
  "fields": [
    {"name": "sender_name", "description": "Full name of the person who sent the email", "data_type": "string"},
    {"name": "sender_email", "description": "Email address of the sender", "data_type": "string"},
    {"name": "company_name", "description": "Company or organization the sender represents", "data_type": "string"},
    {
      "name": "inquiry_type",
      "description": "The primary category of this inquiry",
      "data_type": "enum",
      "enum_options": [
        {"name": "pricing", "description": "Pricing or cost inquiry"},
        {"name": "demo_request", "description": "Request for a product demo"},
        {"name": "support", "description": "Technical support or help request"},
        {"name": "partnership", "description": "Partnership or integration inquiry"},
        {"name": "other", "description": "Other inquiry type"}
      ]
    },
    {
      "name": "urgency",
      "description": "How urgent this request appears based on language and deadlines mentioned",
      "data_type": "enum",
      "enum_options": [
        {"name": "low", "description": "No urgency signals"},
        {"name": "medium", "description": "Moderate urgency or soft deadline"},
        {"name": "high", "description": "Explicit deadline or urgent language"}
      ]
    },
    {
      "name": "topics",
      "description": "Products or areas of interest mentioned in the email",
      "data_type": "multi_select",
      "enum_options": [
        {"name": "product_a", "description": "Product A"},
        {"name": "product_b", "description": "Product B"},
        {"name": "enterprise", "description": "Enterprise plan or features"},
        {"name": "integration", "description": "Integration or API capabilities"},
        {"name": "pricing", "description": "Pricing or billing"},
        {"name": "security", "description": "Security or compliance"}
      ]
    },
    {
      "name": "summary",
      "description": "A one-sentence summary of what the sender is asking for",
      "data_type": "string"
    }
  ]
}

Process a Document (Text Input)

When you already have the email body as a string (from a mail API, webhook, or IMAP client), send it directly as text instead of uploading a file.
curl -X POST 'https://api.anyformat.ai/v2/workflows/YOUR_WORKFLOW_ID/run/' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "From: Maria Lopez <maria@acmecorp.com>\nSubject: Enterprise pricing for Q2\n\nHi,\n\nI am the VP of Engineering at Acme Corp (500+ employees). We are evaluating document processing solutions for our finance team and need enterprise pricing for Product A and Product B.\n\nWe have a hard deadline of April 1st for vendor selection. Could we schedule a demo this week?\n\nBest,\nMaria Lopez"
  }'

Get Results

# Poll for results
max_attempts = 60
base_delay = 5

for attempt in range(max_attempts):
    response = requests.get(
        f"https://api.anyformat.ai/v2/files/{file_id}/extraction/",
        headers={"Authorization": f"Bearer {API_KEY}"}
    )

    if response.status_code == 200:
        results = response.json()
        break
    elif response.status_code == 412:
        delay = min(base_delay * (1.5 ** min(attempt, 5)), 30)
        time.sleep(delay)
    else:
        raise Exception(f"Error: {response.json()['detail']}")
else:
    raise TimeoutError("Processing timed out")

# Route the lead based on extracted data
lead = {
    "name": results["sender_name"]["value"],
    "email": results["sender_email"]["value"],
    "company": results["company_name"]["value"],
    "type": results["inquiry_type"]["value"],
    "urgency": results["urgency"]["value"],
    "topics": results["topics"]["value"],
}

if lead["urgency"] == "high":
    print(f"HIGH PRIORITY: {lead['name']} from {lead['company']}")
    print(f"  Inquiry: {lead['type']}, Topics: {', '.join(lead['topics'])}")

Example Response

{
  "sender_name": {"value": "Maria Lopez", "confidence": 98},
  "sender_email": {"value": "maria@acmecorp.com", "confidence": 99},
  "company_name": {"value": "Acme Corp", "confidence": 95},
  "inquiry_type": {"value": "demo_request", "confidence": 91},
  "urgency": {"value": "high", "confidence": 88},
  "topics": {
    "value": ["product_a", "product_b", "enterprise", "pricing"],
    "confidence": 87
  },
  "summary": {
    "value": "VP of Engineering at Acme Corp requesting enterprise pricing and a demo for Product A and B, with an April 1st vendor selection deadline",
    "confidence": 90
  }
}

Tips

Text input is ideal when you already have content as a string. It avoids file I/O overhead and works well for emails, chat transcripts, and form submissions.
A string field with a descriptive prompt like “A one-sentence summary of what the sender is asking for” acts as a mini-summarizer, giving you a structured summary alongside the extracted fields.
  • Write detailed enum_options descriptions to help distinguish between similar categories. “pricing” vs “demo_request” can be ambiguous without good descriptions.
  • multi_select captures all relevant topics even when the email discusses multiple products or areas.
  • For .eml or .msg files, use the standard file upload instead of text input to preserve headers and attachments.
  • Process emails in bulk by looping over your inbox and sending each body as text.

Next Steps

Run Workflow

See all input methods: file upload and text

Webhooks

Use webhooks instead of polling for production email pipelines