Agent-first documentation

Your agent succeeds on its first Synorb session.

Use the operational guide and machine-readable contract below. They are written for agents that must retrieve live, source-grounded context without trial-and-error usage allowance loss.

Start in this order

1. Provision a credential. Send POST https://api.synorb.com/api/connect/demo-key with the body {"client": "<your agent name>"}. The answer holds a Synorb Key that works for both MCP and REST. A person can press Generate Free Agent Key on /connect. Store it only in the host or server secret store. Agent clients that should not hold a long-lived key can use OAuth 2.0 instead.
2. Read the runtime guide. agent-guide.md has copy-paste recipes, exact request/response pairs, usage rules, and failure contracts.
3. Resolve, scope, then pull. Resolve tags with GET /ontology/tags, choose explicit stream_ids, then use MCP or REST.
Authorization: Bearer YOUR_SYNORB_KEY

Authenticate

Both credentials are sent the same way — Authorization: Bearer <value> — and both work on MCP and REST. The Synorb Key is the default and is not deprecated.

Choose the transport

Personal agents start with Beacons. Personal agents work in three modes (Watch, Answer, Pull): propose one to three Beacons from what you already know about your user (offering the starter Beacons if you know little), offer to save a Beacon after answering a specific question, and pull Manifests for one-off asks. Save a Beacon only after the user says yes. Beacons are available on every plan, with a per-plan count cap.

For a live website or app, a coding agent may use MCP to understand coverage while building, but the deployed product should call REST from a server-side route. Never put a Synorb Key in browser code. Preserve source citation URLs in the rendered interface.

Non-negotiable query rules

  1. Ontology first. Never guess a tag name. Resolve it through /ontology/tags. An unknown tag can return an empty result without an error.
  2. Scope with stream_ids. Select them from catalog/details first. An explicit empty stream_ids list is rejected with empty_stream_ids at zero usage; omitted scope is deliberately broad. required_surfaces is not reliable execution scope.
  3. Plan before REST execution. Call POST /manifests/plan, retain the request exactly, then call POST /manifests/exec with the identical fields plus plan_token.
  4. Honor the fingerprint. Adding or changing any field, including target_count, invalidates the plan token. A 409 invalid_plan_token requires a free re-plan, not a modified retry.

/manifests/query response diagnostics

These additive fields are part of the public response contract. Treat them as machine-readable routing signals before interpreting an empty page, retrying, or presenting a claim.

FieldHow agents should use it
coverageAuthoritative status and reason for the query outcome. Do not call a zero exact unless coverage is authorized and not an error.
candidate_projectionOnly with include_diagnostics=true. Pre-execution candidate-set proof, including truncation or authorization reasons when Synorb declines to execute a scope.
final_scope_authorizationProof that the final scope matches the authorized request. If authorized is false, correct the scope instead of broadening silently.
citation_contractAlways present in successful query and exec data. status=required means preserve each returned citations/source_url; status=none means the page returned no Manifests.
did_you_meanMachine-readable canonical suggestions for unresolved tags or source-channel names. Ask or retry with the suggested canonical field, not the failed text.
result_fingerprintStable identity for the returned result page after scope, authorization, and pagination are applied. Use it for cache/audit comparisons.

Slim responses

diagnostics, coverage_outcome, candidate_projection and manifest_index are operator/proof blocks that can run tens of KB each, even for a single Manifest — all are dropped by default now, regardless of response_profile. Pass include_diagnostics=true on POST /manifests/query (and its MCP twin synorb-manifests) only if you need the underlying coverage/absence proof; most callers never need this. response_profile="slim" is a separate, additive lever that further drops other operator-only blocks, and trims each Manifest's Brief/Record to citation-grade fields, keeping the usage receipt — tens of KB instead of hundreds for the same page. Neither flag changes which Manifests are returned or billed: quota_charged and the billed count are identical across every combination for the same request.

Billing at a glance

ActionManifest usage allowance
Catalog, details, ontology, account, count/orient, and planZero
Beacon create, list, archive, restore, and deleteZero
Topic-filtered REST execute or Beacon pollOnly returned on-topic Manifests
Previously billed repeated ManifestNot billed again in the same billing period (a repeat in a later period is billed)
Invalid request, planning failure, invalid token, or clean empty resultZero unless a Manifest was returned

Inspect each response's usage and usage receipt. A target count is a ceiling, not permission to fill results with unrelated content.

Pagination

For GET /streams, GET /streams/{id}/manifests, and other GET lists, fetch a non-null next or prev URL verbatim with the same authentication. null means there is no page in that direction.

POST /manifests/query returns opaque, fully-qualified GET next/prev URLs. Follow them verbatim with the same Authorization header; the server-held cursor carries the original scope and is short-lived. If it expires, repeat the original POST. POST /manifests/exec remains POST-only because execution can bill; its page values are hints to copy into the original body and re-plan.

For /manifests/exec, the plan token signs the exact body: remove the previous plan_token, apply the paging values, POST that body to /manifests/plan for a fresh zero-usage token, then POST the exact newly planned body to /manifests/exec with only the new token added. Reusing the old token after changing paging fields returns 409.

When present, data.pagination.count_as_of is an exact count within the published snapshot identified by count_generation; count_basis is published_snapshot. Later writes appear on a later refresh. Keep the same authentication while following query cursors. Independent requests may receive different generations.

Pages are zero-based: page=0 (or page_num=0) is the first page, and starting at 1 skips it. Follow data.pagination.next and prev instead of counting pages yourself.

data.pagination.next and data.pagination.prev apply to Streams and Manifest queries; GET /v3/beacons uses top-level next/prev. Legacy query fields page, page_num, page_size, has_more, and next_page, plus Beacon limit, offset, and total, remain supported.

Quota and actionable errors

usage.quota_limit, usage.quota_used, and usage.quota_remaining are the response balance snapshot. usage.manifests_billed_this_call and data.quota.manifests_billed_this_call are the call receipt; Manifest-query responses also expose settled data.quota.quota_used and data.quota.quota_remaining. Planning responses can additionally include estimated_max_billed_on_execution and remaining_hard_cap.

For 401 synorb_key_invalid or synorb_key_expired, send POST https://api.synorb.com/api/connect/demo-key for a fresh key, or create an account at /signup. For 404, correct the request from this documentation and openapi.json. For 409, re-plan; for 422, correct the named field; for 429, honor Retry-After; and never call 503 or coverage.status=error an empty result.

Demo-key data freshness

Daily-delivery plans (including the 72 Hour Agent Demo) have an available_through/latest_allowed ceiling that normally trails the wall-clock date by one day (lag_days=1 is normal, not a fault), so relative days and lookback_hours values default to that ceiling: days=1 means the latest available day, not necessarily today.

Inspect GET /account temporal diagnostics and the query response's temporal object (refresh_tier, available_through, lag_days, and effective window) before interpreting an empty recent result.

Beacons: watch vs. pull

Use a Beacon for a reusable watch. Propose it from what you know about your user (or the starter Beacons, tag starter, when you know little) and save it only after a yes. Pull directly for a one-off answer, then offer to save it. Synorb does not run Beacon schedules or push: your runtime pulls on its own cadence with an explicit lookback window and dedupes by Manifest id. A Beacon's natural_language_intent is descriptive only. Convert intent to selected stream_ids and canonical topic_filters first.

[{"tag_id":"tag_123","tag_name":"Payment Systems","tag_type":"topic"}]

Run a saved Beacon through GET /streams/{id}/manifests?beacon_id=... with a time window. Do not use POST /manifests/query to execute it. The full create, poll, archive, restore, and delete lifecycle is in the agent guide.

Machine-readable entry points

Coding agents

Give the build agent the guide before it writes an integration. It will learn the two-key boundary: MCP for the agent's exploratory session and server-side REST for the shipped user experience, with citations preserved.