Company intelligence brief
Give a website and one goal, get back a structured brief on the company that your own AI model or your team can act on straight away: what the company sells and to whom, the market and buyer language, real competitors, what buyers ask and object to in public discussions, and a ready playbook for the chosen goal. Every factual item links to the evidence it came from.
One brief serves one goal:
focus | Built for |
|---|---|
reddit_promotion | promoting the company on Reddit: communities that matter, search queries that surface relevant threads, buyer questions and objections, safe claims |
seo_web | promoting the company in search: commercial queries by intent, who owns the results today, content gaps |
competitor_intel | studying the company as a competitor: positioning, pricing, features, what its customers complain about |
A second goal for the same company is a second request. Within 7 days it reuses the site
reading and company profile from the first brief, so it starts faster and both briefs
describe the company the same way; the job shows "core_reused": true.
Company intelligence is switched on for a key on request: write to support@omev.be. The brief is charged to the key's usual balance.
Depth and price
depth | Price per delivered brief | What is in it |
|---|---|---|
standard (default) | $0.99 | the company brief without the audience voice: 3–6 competitors and the standard search; the buyer-voice sections are marked as not included |
extended | $1.99 | everything in standard, plus the audience voice (up to 300 buyer comments read, with forums and other sources added for narrow niches), 7–8 competitors and a wider search |
You pay once per brief, when you first download a finished result, by how complete it is:
| Completeness of the brief | Charge |
|---|---|
| 75% or more | the full price |
| 40–74% | 70% of the price |
| 15–39% | 30% of the price |
| below 15% | free |
A partial charge is rounded down to whole cents.
The job shows completeness_percent and charged_usd. A brief that fails, a site we cannot
read, a cancelled job and repeated downloads of the same brief are not charged. A
domain report includes the extended brief together with community and
AI visibility research.
Start a brief
curl -sS https://llmapi.omev.be/v1/cig/jobs/create \
-H "Authorization: Bearer $OMEV_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://vessi.com",
"focus": "reddit_promotion",
"depth": "standard",
"client_ref": "acme-client-17",
"idempotency_key": "acme-17-vessi-reddit-2026-09"
}'
| Field | Required | Meaning |
|---|---|---|
url | yes | the company website; a public http/https address |
focus | yes | one of reddit_promotion, seo_web, competitor_intel |
depth | no | standard (default) or extended |
market | no | a country or region, such as "US", or a list of up to 10, such as ["EU", "DE"] |
language | no | a language code such as "en", or a list of up to 6, such as ["en", "de"] |
voice | no | who the suggested replies speak as: brand (default) or community_member; OmevAI never posts anything |
max_age_days | no | 1–1830; discussion threads older than this are left out of the playbook |
client_ref | no | your own label for the end client (agencies: split spend per client) |
idempotency_key | no | 8–200 characters; repeating it returns the same job instead of starting a new one |
callback_url | no | a public https address we call when the brief is finished (see Notification) |
callback_secret | no | 16–200 characters; with it every notification is signed |
Before a brief starts, we check that the balance of your key covers its price. If it does
not, the answer is 402 INSUFFICIENT_BALANCE and nothing starts.
The answer is 202 with the job:
{
"job": {"id": "cig_…", "status": "queued", "stage": "", "focus": "reddit_promotion",
"depth": "standard", "client_ref": "acme-client-17", "charged_usd": 0},
"idempotent_replay": false,
"poll_after_seconds": 10
}
Many sites at once
Send up to 50 briefs in one call. Each item takes the same fields as a single brief.
curl -sS https://llmapi.omev.be/v1/cig/jobs/batch \
-H "Authorization: Bearer $OMEV_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{"url": "https://vessi.com", "focus": "reddit_promotion", "client_ref": "acme-17"},
{"url": "https://vessi.com", "focus": "seo_web", "client_ref": "acme-17"},
{"url": "https://allbirds.com", "focus": "competitor_intel", "client_ref": "acme-17",
"callback_url": "https://hooks.example.com/omev", "callback_secret": "a-long-random-secret"}
]
}'
The answer is 202 with one entry per item, in the same order. An item with a mistake
gets its own error and does not stop the others:
{
"items": [
{"index": 0, "job": {"id": "cig_…", "status": "queued", …}, "idempotent_replay": false},
{"index": 1, "job": {"id": "cig_…", "status": "queued", …}, "idempotent_replay": false},
{"index": 2, "error": {"code": "INVALID_URL", "message": "…"}}
],
"poll_after_seconds": 10
}
The balance must cover all valid items together; otherwise the call returns
402 INSUFFICIENT_BALANCE and no item starts. Two goals for the same site in one call
share one site reading.
Follow the job
A standard brief takes 10–25 minutes, an extended one up to about an hour: the service
reads the site, searches, checks competitors and reads buyer discussions. Poll every
15–30 seconds.
curl -sS https://llmapi.omev.be/v1/cig/jobs/get \
-H "Authorization: Bearer $OMEV_API_KEY" \
-H "Content-Type: application/json" \
-d '{"job_id": "cig_…"}'
status is queued, running, then one of completed, partial, failed, cancelled.
While running, stage shows where the work is, for example site_read, business_mix,
profile_extract, research_plan, market_frame, competitors, search,
communities, audience, claim_verify, synthesis, thread_tone, moderation. A
brief that reuses an earlier site reading shows site_core_reused instead of the first
three. Treat the list as informative: new steps can appear.
partial is a delivered brief with some part not completed; the reason is listed in
evidence_base.limitations, and evidence_base.coverage.completeness shows every section
with what was found, its target and its minimum. On failed, error.code says why, for
example site_unreadable when the site blocks automated visits.
To stop a job, send the same body to /v1/cig/jobs/cancel.
Notification when a brief is ready
With callback_url, you do not need to poll. When the job reaches completed,
partial, failed or cancelled, we send a POST to that address:
{"event": "cig.job.finished", "job": {"id": "cig_…", "status": "completed", …}}
| Header | Meaning |
|---|---|
X-Omev-Event-Id | the job id; use it to ignore repeated deliveries |
X-Omev-Signature | sha256= and the hex HMAC-SHA256 of the raw body, keyed with your callback_secret (sent only when you gave a secret) |
Answer with any 2xx status. If the call fails, we try twice more, after 10 seconds and
after 60 seconds. The outcome is shown in job.callback_status. The notification carries
only the job; download the brief with /v1/cig/jobs/result as usual.
Check the signature before you trust the body:
import hashlib, hmac
def is_from_omev(raw_body: bytes, header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header or "")
Download the brief
curl -sS https://llmapi.omev.be/v1/cig/jobs/result \
-H "Authorization: Bearer $OMEV_API_KEY" \
-H "Content-Type: application/json" \
-d '{"job_id": "cig_…"}'
The response holds job, profile (the full brief) and stage1 (a short summary of the
same brief with ten fields). Before the job finishes the call returns 409 JOB_NOT_READY.
The brief has nine sections:
| Section | Contents |
|---|---|
meta | goal, depth, target URL, market, generation time |
company | product, positioning, business mix, features, offer, trust signals |
market | buyer profile (ICP), market frame, keywords, buyer queries |
problems | problems the brand solves, frustrations in the category |
brand_perception | complaints, praise and mentions found in public sources |
competition | competitors (direct, adjacent, status_quo) with the reason each one competes |
audience | buyer questions, objections, expectations, verbatim buyer quotes |
playbook | the plan for the goal: communities, search queries, messaging, next actions, claim guardrails |
evidence_base | every source and quote the brief relies on, coverage numbers, limitations |
Items carry evidence_ids pointing into evidence_base.evidence, where each entry has
the source url and the exact quote. Claims are marked as stated (the company says
so), observed (seen in independent sources) or inferred (our conclusion). When you
pass the brief to an AI model, tell it to state only stated and observed items as
facts and never to use anything listed in playbook.reply_guardrails.do_not_claim.
Errors
| Code | When |
|---|---|
401 | missing or invalid API key |
402 INSUFFICIENT_BALANCE | the balance of the key does not cover the brief (or all valid items of a bulk call) |
404 JOB_NOT_FOUND | unknown job, or a job that belongs to another account |
409 JOB_NOT_READY | the result was requested before the job finished |
422 INVALID_URL | the address is not a public website |
422 INVALID_FOCUS, 422 INVALID_DEPTH, 422 INVALID_VOICE | a value outside the lists above |
422 INVALID_MARKET, 422 INVALID_LANGUAGE, 422 INVALID_MAX_AGE, 422 INVALID_IDEMPOTENCY_KEY | a field out of range: more than 10 markets, more than 6 language codes, an age outside 1–1830 days, a key outside 8–200 characters |
422 INVALID_CALLBACK_URL, 422 INVALID_CALLBACK_SECRET | the notification address is not a public https address, or the secret is not 16–200 characters |
422 INVALID_REQUEST, 422 BATCH_TOO_LARGE | a bulk call without items, with an item that is not an object, or with more than 50 items |
429 | too many requests; retry after a short pause |
Every error has the same shape: {"error": {"code": "INVALID_FOCUS", "message": "…"}}.
A 401 for a wrong key and a 429 work the same way for every OmevAI API; see Errors
for their format.