Getting started

Generate your first profile

From zero to a verified business profile in under five minutes.

Prerequisites

You only need two things:

  1. A Lumen Sieve account — create one free.
  2. An API key — generate one from the API keys page in the dashboard.
Tip: Use a test key (lumen_test_sk_…) while you're building. Test keys have the same API surface as live keys but don't count against your billing.

1. Start a lookup

Send a POST request to /v1/profiles/lookup with a businessName and a countryHint (requires the profiles:write scope). Lumen Sieve resolves on name + country — this is the path we've actually tested and verified end-to-end. This is asynchronous — a cold resolve runs the full discovery → crawl → extraction → reconciliation pipeline, which can take anywhere from a few seconds to a few minutes, so the endpoint returns immediately with a businessId to poll rather than the finished profile.

cURL
bash
curl -X POST https://api.lumen.com/v1/profiles/lookup \
  -H "Authorization: Bearer lumen_test_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "businessName": "Blispa Barbershop & Spa",
    "countryHint": "KE",
    "mode": "full"
  }'
# => 202 Accepted
# { "businessId": "616de6d1-...", "pollUrl": "/v1/profiles/616de6d1-...", "status": "processing" }
TypeScript
typescript
const submit = await fetch('https://api.lumen.com/v1/profiles/lookup', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.LUMEN_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    businessName: 'Blispa Barbershop & Spa',
    countryHint: 'KE',
    mode: 'full',
  }),
});
const { businessId } = await submit.json(); // 202 Accepted

// Poll until the resolve finishes.
let profile;
while (true) {
  await new Promise((r) => setTimeout(r, 3000));
  const poll = await fetch(`https://api.lumen.com/v1/profiles/${businessId}`, {
    headers: { Authorization: `Bearer ${process.env.LUMEN_API_KEY}` },
  });
  if (poll.status === 202) continue; // still processing
  const body = await poll.json();
  if (!poll.ok) throw new Error(body.error?.message ?? 'lookup failed');
  profile = body.profile;
  break;
}
console.log(profile.business.trade_name.value);
Python
python
import os, time, requests

API_KEY = os.environ["LUMEN_API_KEY"]
BASE = "https://api.lumen.com"
headers = {"Authorization": f"Bearer {API_KEY}"}

submit = requests.post(
    f"{BASE}/v1/profiles/lookup",
    headers={**headers, "Content-Type": "application/json"},
    json={"businessName": "Blispa Barbershop & Spa", "countryHint": "KE", "mode": "full"},
)
submit.raise_for_status()  # 202 Accepted
business_id = submit.json()["businessId"]

# Poll until the resolve finishes.
while True:
    time.sleep(3)
    poll = requests.get(f"{BASE}/v1/profiles/{business_id}", headers=headers)
    if poll.status_code == 202:
        continue  # still processing
    poll.raise_for_status()
    profile = poll.json()["profile"]
    break

print(profile["business"]["trade_name"]["value"])

The mode field controls speed vs. depth:

ModeTypical latencyUse when
previewA few secondsYou want fast partial data (e.g. CRM enrichment)
fullTens of seconds to a few minutesYou need the complete profile (default)

Don't want to poll at all? See Lookup notifications to have Lumen Sieve call a URL of yours the moment a lookup finishes.

2. Read the response

Once GET /v1/profiles/{businessId} stops returning 202, a 200 carries the finished profile object — a nested, section-based document (see Data model for the full shape), not a flat record. Every field that has data is wrapped with its own confidence and source URLs:

Response (truncated, real example)
json
{
  "profile": {
    "business": {
      "trade_name": {
        "value": "Blispa Barbershop & Spa",
        "metadata": {
          "confidence": 0.995,
          "sources": ["https://blispabarbershop.co.ke/", "https://blispabarbershop.co.ke/about"],
          "last_verified": "2026-07-31T23:35:12Z"
        }
      }
    },
    "contact": {
      "phones": [{ "number": "+254746200969", "purpose": "main", "metadata": { "confidence": 0.995, "sources": ["..."] } }]
    },
    "metadata": {
      "confidence_score": 0.6084,
      "completeness_score": 0.6667,
      "sources_queried": 6,
      "sources_successful": 6
    }
  },
  "profileId": "ebbbe097-d475-4051-b358-8c638c85b32c"
}

3. Re-fetch a cached profile

Every profile is stored under the businessId from step 1. GET always returns exactly what's persisted, immediately, however old it is — it never re-resolves on its own. To get fresh data, call POST /v1/profiles/lookup again with the same businessName + countryHint: Lumen Sieve reuses the cached profile if it's still within the freshness window, or transparently runs a new resolve if it's gone stale. Pass force_refresh: true to always force a fresh resolve regardless of freshness.

cURL
bash
curl https://api.lumen.com/v1/profiles/616de6d1-... \
  -H "Authorization: Bearer lumen_test_sk_YOUR_KEY"

Next steps