Docs / Developers / REST API v1 overview

REST API v1 overview

Last updated: 29 October 2026

Stravax Engage ships a REST API (v1) for tenant integrations. It is authenticated with an API key from Settings > Connections > API keys (in the earlier look: Settings > Developer). Sending uses the same pipeline as the agent inbox, so delivery, consent, billing, and window rules stay the same.

The machine-readable contract is available at /api/v1/openapi.json. This guide remains the task-oriented companion.

What can I do with the API today?

Acquisition references (pending attribution release)

POST /api/v1/acquisition-refs is API-key-only and requires leads:write plus a nonempty Idempotency-Key. It accepts installationKey, captureId, captureProof and at least one of phone or email. The server verifies the authenticated workspace, integration, installation, subject and existing capture. No body field selects an org, journey, destination or permission.

A confirmed first issuance returns 200 {ok:true,acquisitionRef,expiresAt} with no-store. The capability is never stored in a response cache, URL, log, queue or export. Its reference and capability-free completion must commit together. A completed same-key retry returns status 409 and exactly {"ok":false,"error":"acquisition reference already issued","code":"acquisition_ref_already_issued"}, including when the retry body is malformed. A lost first response requires a new key to request another reference; all references still share the same receipt's lead-binding fence. A pending request returns the existing 409 idempotent_replay_pending. Unknown commit outcomes retain the pending claim.

Lead creation accepts optional acquisitionRef. Omission remains valid and saves unknown origin, which is held for Meta while eligible non-Meta routes retain their contract. Invalid references return fixed 400 invalid_acquisition_ref, an authorized conflicting claim returns 409 acquisition_ref_conflict, and a known unavailable admission returns releaseable 503 acquisition_unavailable. The Slice A joint candidate composes reference redemption through the pinned V3 server-owned construction and atomic admission fence. Runtime proof and release remain pending. This is not an activated integration.

The released contract must commit reference claim, lead, acquisition binding, permission/readiness and intake intent in one native transaction. Exact durable replay returns the surviving original lead even after response-cache expiry; erasure cannot recreate it. Optional browser metadata rejection must not discard an otherwise valid service lead. Generic fields cannot supply authoritative origin, dataset, consent or native-source assertions.

How do I authenticate requests?

Send your API key as a bearer token in the Authorization header:

Authorization: Bearer <your-api-key>

The key determines which organization the request belongs to, you never pass an organization id yourself. A key from one organization has no visibility into another organization's contacts, messages, or resources.

What happens if I send outside the messaging window?

The same thing that happens in the inbox: if the contact's session window has expired, the API returns the identical error the inbox's session route would return for the same contact. There's no separate error format to learn for API sends versus inbox sends.

Does the API respect consent rules?

Yes. Sending a marketing template to a contact who hasn't opted in is blocked, the same as it would be from the inbox, rather than silently allowed because the request came from your own system.

Are there rate limits?

Yes, at two levels: a per-key request rate limit, and a monthly request ceiling included in your plan. Going over either returns an error rather than queueing or degrading silently. See current plans for the specific numbers on your plan, and upgrade in-app if you need more headroom.

Where do I manage my keys?

Keys are created, viewed, and revoked from Settings > Connections > API keys. See API keys for how scopes and revocation work, and Outbound webhooks if you also want Stravax Engage to push events to your systems instead of only pulling and pushing through this API.

Pagination, retries, and tracing

List responses contain next_cursor. Pass it as cursor to continue, and keep going until it comes back null, which is the only reliable end-of-list signal: a page may be shorter than your limit and still have more after it. limit defaults to 100 and cannot be greater than 100 (a larger value is refused rather than quietly reduced). A cursor is opaque, so read it only as a value to hand back.

Two page sizes are set by the product rather than by you. A conversation's messages come back at most 50 at a time, whatever limit you ask for, because that is the page size the agent inbox itself reads. Conversations are listed channel by channel, newest activity first within each channel, rather than as one merged timeline across every connected number.

Send Idempotency-Key on every write. For 24 hours, a replay identity is your organization, the API operation, the API key that made the call, and the key value. A repeated completed request with that same identity returns its first stored response, even if the retry body differs. Use a fresh key for a new logical operation.

Each API operation explicitly marks only its own refusals that happened before any durable write as releasable, so you can correct that request and retry with the same key. A not_found code is not globally releasable: the note route releases its visibility refusal before its insert, while a contact upsert's post-insert re-read miss is stored and replayed. Other claims are retained. If an original request stops after its claim is stored but before its response is saved, the same identity can return 409 idempotent_replay_pending for up to 24 hours. A nightly reaper removes expired replay rows, but never takes over a pending request because retrying its side effect could send or create it twice. On a quiet night it exits after its first short page; under sustained load it continues only within a 20-second wall-clock budget.

Every v1 response contains X-Request-Id. You may provide one and it is echoed back, which helps support trace a failed call without sharing request content.

Acquisition references, pending release

POST /api/v1/acquisition-refs is an API-key-only leads:write operation. Its body is {installationKey,captureId,captureProof,phone?,email?}, with a phone or email required. The installation and captured website receipt must belong to that authenticated organization and the receipt must still be eligible. The reference is bound to that API key and subject; OAuth and MCP cannot mint it.

This issuer requires a nonempty Idempotency-Key. A missing key returns 400 idempotency_key_required. The first confirmed successful call returns {ok:true,acquisitionRef,expiresAt} once. Reference creation and the exact capability-free replay completion commit in one transaction. A completed retry, including one with a different or malformed body, returns status 409 and {ok:false,error:"acquisition reference already issued",code:"acquisition_ref_already_issued"}. The successful capability is never stored in the replay body. If the first response is lost, request another reference with a fresh key; references sharing one acquisition receipt still cannot create different deals from that receipt.

Invalid references have a fixed 400 invalid_acquisition_ref response. An authorized conflicting redemption returns 409 acquisition_ref_conflict. A known pre-write storage refusal can return releasable 503 acquisition_unavailable. An unknown commit outcome keeps the replay claim pending and is not permission to reissue or retry the side effect. Observe the existing 409 idempotent_replay_pending response until its retained state is resolved. Normal existing API write replay behavior is unchanged.

Keep captureProof and acquisitionRef out of URLs, logs, exports, provider payloads and third-party analytics. Possessing a reference grants no advertising measurement permission, destination, provider eligibility or campaign credit.

More in Developers