Getting started
Generate your first profile
From zero to a verified business profile in under five minutes.
Prerequisites
You only need two things:
- A Lumen Sieve account — create one free.
- An API key — generate one from the API keys page in the dashboard.
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 -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" }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);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:
| Mode | Typical latency | Use when |
|---|---|---|
preview | A few seconds | You want fast partial data (e.g. CRM enrichment) |
full | Tens of seconds to a few minutes | You 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:
{
"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 https://api.lumen.com/v1/profiles/616de6d1-... \
-H "Authorization: Bearer lumen_test_sk_YOUR_KEY"Next steps
- Authentication — scopes, key rotation, IP allowlists.
- API reference — every endpoint documented.
- Errors — every error code and whether to retry.
- Rate limits & plans — quotas and requests-per-minute by plan.
- Data model — understand confidence scores and field attribution.
