API reference

REST API reference

Base URL: https://api.lumensieve.com · All endpoints require a Bearer token · All bodies and responses are JSON.

Prefer a machine-readable spec (e.g. for codegen, or pointing an AI coding assistant at it)? The full OpenAPI 3.0 spec (also at /openapi.json) is served directly by the API itself, so it never drifts from what's actually deployed.

Profiles

POST/v1/profiles/lookup

Kick off a business profile resolve — by name + country, or by domain alone when you already know the business's website. Requires the profiles:write scope. This is asynchronous — a cold full resolve runs the complete discovery → crawl → extraction → reconciliation pipeline and typically takes a few minutes (a preview resolve returns fast partial data in a few seconds), so this endpoint returns immediately and you poll for the result (see below).

Request body

FieldTypeRequiredDescription
businessNamestringConditionalCompany name — required unless domain is given.
countryHintstringConditionalISO 3166-1 alpha-2 country code — required when businessName is given
domainstringConditionalThe business’s website domain (e.g. "acmecoffee.com") — an alternative to businessName + countryHint. See "Lookup by domain" below.
mode"preview" | "full"—preview = fast partial data; full = complete profile (default: full)
localityHintstringConditionalState, province, or city — required when countryHint is a federated country (see below); never required for a domain lookup
force_refreshboolean—Bypass the cached profile (if any) and run a fresh resolve

Federated countries require a locality hint. For US, IN, BR, CA, AU, DE, MX, and NG, business names commonly repeat across many distinct, unrelated locations (a "Joe's Pizza" in a dozen different states) — name + country alone isn't enough to reliably identify one. Omitting localityHint for these countries returns MISSING_REQUIRED_FIELD; supplying one that isn't a real state, province, or city in that country returns INVALID_FIELD_VALUE. This requirement never applies to a domain lookup — a domain is inherently unambiguous.

Request body (by name + country)

json
{
  "businessName": "Blispa Barbershop & Spa",
  "countryHint": "KE",
  "mode": "full"
}

Request body (by domain)

No countryHint or localityHint needed — the engine deep-crawls the given domain first, extracts the business's real name and every fingerprint (phone, email, address, social links) directly from the site, and derives the country from the domain itself (its country-code TLD, or a phone number found on the site) before the rest of the resolve runs. This is often a cleaner match than name + country: you've already supplied an unambiguous anchor, so there's no name to disambiguate.

json
{
  "domain": "artcaffe.co.ke",
  "mode": "full"
}

Response — 202 Accepted

json
{
  "businessId": "616de6d1-7732-4ece-a551-5e3187923aa8",
  "pollUrl": "/v1/profiles/616de6d1-7732-4ece-a551-5e3187923aa8",
  "status": "processing"
}

Poll pollUrl (i.e. GET /v1/profiles/{businessId}) every few seconds until it stops returning 202. See that endpoint below for the shape of the finished result.

GET/v1/profiles/{id}

Poll for a resolve's result, or re-fetch an already-completed profile by its business ID — the same ID returned by POST /v1/profiles/lookup. Requires profiles:read.

Query parameters

ParameterTypeDescription
include_attributionsbooleanInclude per-field source attribution in the response

Response by state

HTTP statusMeaning
202Still resolving — { "businessId": "…", "status": "processing" }. Poll again shortly.
200Resolve finished — { "profile": { /* see Data model */ }, "profileId": "…" }
500Resolve finished but failed — { "error": { "code": "INTERNAL_ERROR", "message": "…" } }
POST/v1/profiles/{id}/refresh

Force a full re-generation of a profile, bypassing all caches. Counts against your lookup quota.

POST/v1/profiles/{id}/corrections

Submit a data correction for a specific field. Corrections are reviewed and applied to future profile generations.

Request body

FieldTypeRequiredDescription
field_pathstring✓Dot-path of the field to correct (e.g. "contact.website")
correct_valueany✓The correct value as JSON
explanationstring—Optional human-readable explanation
GET/v1/profiles/{id}/attribution/{fieldPath}

Return per-field source attribution — which sources contributed to a specific field and at what confidence.

Not yet available in production — this currently returns 501 NOT_IMPLEMENTED. Every field in the main profile response already carries its own metadata.sources and metadata.confidence inline (see Data model), which covers most attribution needs today.

POST/v1/profiles/{id}/ask

Ask a natural language question about a profile. Requires the ask_lumen feature on your plan.

Request body

FieldTypeRequiredDescription
questionstring✓Natural language question, max 1000 characters
conversation_historystring[]—Previous turns for multi-turn conversations
POST/v1/profiles/lookup/stream

Stream profile generation as Server-Sent Events. Each event is a JSON object. The stream ends with an event: done sentinel.

Event types

typeDescription
source_discoveredA data source URL was found
source_completedA source finished extraction
section_completedA profile section (e.g. contact) is ready
partial_profilePreview-quality partial profile available
completeFull profile is ready
errorA non-fatal error occurred
GET/v1/profiles

List profiles in the account, paginated.

Query parameters

ParameterTypeDescription
cursorstringPagination cursor from a previous response
limitnumberItems per page (default 20, max 100)
qstringFilter by name or domain

Lookup notifications

Get called back when a lookup finishes instead of polling — see Lookup notifications for the full guide (payload shape, signature verification). Requires webhooks:manage. Covers only profile.resolved / profile.failed — not a general eventing system.

POST/v1/webhooks/subscriptions

Register a URL to be called when a lookup you started resolves or fails.

GET/v1/webhooks/subscriptions

List your registered URLs.

DELETE/v1/webhooks/subscriptions/{id}

Remove a registered URL.

GET/v1/webhooks/deliveries

List recent delivery attempts across your subscriptions.

GET/v1/webhooks/deliveries/{id}

Inspect one delivery attempt.

POST/v1/webhooks/deliveries/{id}/retry

Manually retry one delivery.

GET/v1/webhooks/dead-letter

List deliveries that exhausted all automatic retries.

POST/v1/webhooks/dead-letter/{id}/replay

Re-attempt a dead-lettered delivery.

POST/v1/webhooks/test

Send a synthetic test event to a URL before relying on it.

Billing

POST/v1/billing/portal

Create a short-lived Creem customer portal session. Redirect the customer to overview_url to manage their payment method or cancel — both are handled on Creem's own hosted pages, and Creem's webhook syncs any resulting change back to your account.

Response

json
{
  "overview_url": "https://www.creem.io/my-orders/..."
}

cancel_url and update_payment_method_url may also appear in this object, but Creem's portal is a single page rather than separate deep links, so in practice they are omitted — send the customer to overview_url and let them navigate from there.

GET/v1/billing/invoices

List the account's billing/invoice history.

GET/v1/billing/invoices/{id}/pdf

Get a short-lived (~1 hour) signed PDF URL for one invoice.

Usage & account

GET/v1/usage

Full usage metrics for the current billing period, including per-resource used/limit/remaining.

GET/v1/usage/summary

Condensed summary view matching the dashboard's usage page.

GET/v1/usage/timeseries

Daily usage breakdown for the current billing period.

GET/v1/account

Account details including tier, features enabled, and support info.

POST/v1/account/keys

Create a new API key. The rawKey in the response is shown exactly once.

GET/v1/account/keys

List all active API keys (raw keys are never returned — only metadata).

DELETE/v1/account/keys/{id}

Revoke an API key immediately. Requests using the revoked key fail within 60 seconds.

Health checks

GET/health

Liveness check. Returns 200 OK if the gateway process is running. No auth required.

GET/ready

Readiness check. Returns 200 OK when all downstream services are reachable. No auth required.