AI92 لائیو ہے - ہمارا عالمی سافٹ لانچ جاری ہے: پورا پلیٹ فارم پہلے 30 دنوں کے لیے دنیا بھر میں کھلا ہے۔
دستاویزات کا مینو

یہ ڈویلپر دستاویزات فی الحال صرف انگریزی میں ہیں۔ کوڈ اور API کا رویہ ہر علاقے میں یکساں ہے۔

Account, Billing, Webhooks, OAuth & Brands API

Platform management surfaces. Account management is free — no credits are charged for reading or configuring your account, keys, webhooks, or OAuth apps. The only money surfaces are Billing (Stripe checkout / subscriptions / add-ons) and creating an additional Brand (first brand free; extra sub-brands cost credits). Covered:

  • Account (/v1/account) — account info, credit balance, dashboard overview, billing snapshot, add-on entitlements, sandbox snapshot, auto-recharge, subscription cancel/resume, add-on cancel, rank-tracking keywords, audit-export jobs.
  • API Keys (/v1/account/keys) — create, list, get one, edit, revoke.
  • Usage (/v1/account/usage) — usage time series, activity log, audit-log CSV export.
  • Billing (/v1/billing) — Stripe checkout (packages + pay-as-you-go), invoices, subscription, add-ons.
  • Webhooks (/v1/webhooks) — endpoint CRUD, replay, dead-letter queue.
  • OAuth Apps (/v1/oauth/apps) — register, list, and revoke your own OAuth clients.
  • Brands (/v1/brands) — brand onboarding (first brand free; extra sub-brands cost credits).

Authentication

Authorization: Bearer ai92_live_<key>     # production
Authorization: Bearer ai92_test_<key>     # sandbox

OAuth 2.0 access tokens are also accepted. Mutating requests support Idempotency-Key.


Account

GET /v1/account

Cost: Free

Account info and balance.

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/account \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "id": "acct_88",
  "tier": "growth",
  "credit_balance": 1497,
  "credit_balance_durable": 1500,
  "is_active": true,
  "read_only_mode": false,
  "subscription_tier": "growth",
  "mass_mail_addon_active": false,
  "rank_tracking_addon_tier": null,
  "last_request_at": "2026-06-21T08:55:00Z",
  "created_at": "2026-05-01T12:00:00Z"
}

GET /v1/account/credits

Cost: Free

Current credit balance.

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/account/credits \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{ "balance": 1497, "tier": "growth" }

GET /v1/account/overview

Cost: Free

Dashboard overview: account, usage, subscription, and add-ons in a single call.

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/account/overview \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "account_id": "acct_88",
  "tier": "growth",
  "credit_balance": 1497,
  "rate_limit_rps": 25,
  "is_active": true,
  "read_only_mode": false,
  "read_only_since": null,
  "first_request_at": "2026-05-01T12:05:00Z",
  "last_request_at": "2026-06-21T08:55:00Z",
  "usage_today_credits": 120,
  "usage_this_month_credits": 4310,
  "recent_status_counts": { "2xx": 980, "4xx": 12, "5xx": 0 },
  "webhook_delivery_rate_7d": null,
  "subscription": { "tier": "growth", "status": null, "current_period_end": null, "bundled_credits_per_period": null },
  "addons": { "mass_mail_active": false, "rank_tracking_tier": null }
}

GET /v1/account/billing

Cost: Free

One-shot billing read powering the dashboard billing page: current balance + month-to-date usage, the credit-package catalog, your auto-recharge config, and the most recent ledger entries. Invoices are served separately by GET /v1/billing/invoices; this snapshot returns an empty recent_invoices list so the page renders without a cross-module round-trip.

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/account/billing \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "account_id": "acct_88",
  "credit_balance": 1497,
  "usage_this_month_credits": 4310,
  "packages": [
    { "code": "STARTER", "name": "Starter", "credits": 1000, "price_usd_cents": 2900, "per_credit_usd": 0.029, "savings_pct": 0, "rate_limit_rps": 10 }
  ],
  "auto_recharge": {
    "enabled": false,
    "min_balance_threshold": 500,
    "recharge_package_code": "starter",
    "payment_method_last4": null,
    "payment_method_brand": null,
    "last_triggered_at": null,
    "last_triggered_success": null
  },
  "recent_invoices": [],
  "recent_transactions": [
    { "id": "txn_9a", "type": "debit", "amount": -3, "balance_after": 1497, "service": "contacts", "endpoint": "/v1/contacts/reveal", "created_at": "2026-06-21T08:55:00Z", "reason": null }
  ]
}

GET /v1/account/addons

Cost: Free

Add-on entitlements snapshot for the two subscription add-ons: Mass Mail and Rank Tracking (quota + usage + current period end).

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/account/addons \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "mass_mail": {
    "active": false,
    "recipients_quota": 0,
    "recipients_used_mtd": 0,
    "current_period_end": null
  },
  "rank_tracking": {
    "tier": null,
    "keyword_quota": 0,
    "keyword_count": 0,
    "current_period_end": null
  }
}

GET /v1/account/sandbox

Cost: Free

Sandbox key + usage snapshot: the most recent sandbox key's prefix/last4 and your sandbox request volume (today, this month, and success rate).

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/account/sandbox \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "key_prefix": "ai92_test",
  "key_last4": "9f2a",
  "created_at": "2026-05-01T12:00:00Z",
  "requests_today": 14,
  "requests_this_month": 318,
  "success_rate": 0.9874
}

Auto-Recharge

PATCH /v1/account/auto-recharge

Cost: Free

Update the account's auto-recharge config (top up automatically when the balance drops below a threshold). Any omitted field is left unchanged.

Auth: Bearer

FieldTypeRequiredDescription
enabledboolean / nullNoTurn auto-recharge on or off.
min_balance_thresholdinteger / nullNoTrigger when balance falls below this (>= 0).
recharge_package_codestring / nullNoPackage to buy on trigger (e.g. starter). Case-insensitive.

Request

bash
curl -X PATCH https://api.ai92.ai/v1/account/auto-recharge \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true, "min_balance_threshold": 1000, "recharge_package_code": "growth"}'

Response 200 OK

json
{
  "enabled": true,
  "min_balance_threshold": 1000,
  "recharge_package_code": "growth",
  "payment_method_last4": null,
  "payment_method_brand": null,
  "last_triggered_at": null,
  "last_triggered_success": null
}

Errors

StatusCodeWhen
400invalid recharge_package_coderecharge_package_code is not a known package.

Subscription Management

These manage an existing hybrid subscription / add-on through module-a's Stripe integration. They are free to call; the durable state flips when Stripe's webhook propagates. To start a subscription or add-on, use the Billing endpoints below.

POST /v1/account/subscription/cancel

Cost: Free

Cancel the active hybrid subscription at the end of the current period.

Auth: Bearer

Request

bash
curl -X POST https://api.ai92.ai/v1/account/subscription/cancel \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "tier": "growth",
  "status": "active",
  "current_period_end": "2026-07-01T00:00:00Z",
  "bundled_credits_per_period": 5000,
  "cancel_at_period_end": true
}

Errors

StatusCodeWhen
404(no active subscription)The account has no active subscription.

POST /v1/account/subscription/resume

Cost: Free

Resume a subscription that is scheduled to cancel at period end.

Auth: Bearer

Request

bash
curl -X POST https://api.ai92.ai/v1/account/subscription/resume \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "tier": "growth",
  "status": "active",
  "current_period_end": "2026-07-01T00:00:00Z",
  "bundled_credits_per_period": 5000,
  "cancel_at_period_end": false
}

Errors

StatusCodeWhen
404(no active subscription)The account has no active subscription.

POST /v1/account/addons/mass-mail/cancel

Cost: Free

Cancel the Mass Mail add-on at the end of the current period.

Auth: Bearer

Request

bash
curl -X POST https://api.ai92.ai/v1/account/addons/mass-mail/cancel \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "active": true,
  "recipients_quota": 50000,
  "recipients_used_mtd": 0,
  "current_period_end": "2026-07-01T00:00:00Z"
}

Errors

StatusCodeWhen
404(no active Mass Mail add-on)The account has no active Mass Mail add-on.

Rank Tracking Keywords

Manage the keywords tracked by the Rank Tracking add-on. Requires the add-on to be active (otherwise POST returns 403 NO_RANK_TRACKING_ADDON).

GET /v1/account/addons/rank-tracking/keywords

Cost: Free

List tracked keywords plus the current tier and quota.

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/account/addons/rank-tracking/keywords \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "tier": "pro",
  "quota": 100,
  "keywords": [
    { "id": "kw_01", "term": "crm software", "last_position": 7, "last_checked_at": "2026-06-21T06:00:00Z" }
  ]
}

POST /v1/account/addons/rank-tracking/keywords

Cost: Free

Add a tracked keyword. Returns 201 Created.

Auth: Bearer · Returns 201 Created

FieldTypeRequiredDescription
termstringYesKeyword to track. Length 1255.
domainstring / nullNoDomain to track the keyword for. Max length 255.

Request

bash
curl https://api.ai92.ai/v1/account/addons/rank-tracking/keywords \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"term": "crm software", "domain": "acme.com"}'

Response 201 Created

json
{ "id": "kw_01", "term": "crm software", "last_position": null, "last_checked_at": null }

Errors

StatusCodeWhen
403NO_RANK_TRACKING_ADDONThe Rank Tracking add-on is not active.
403RANK_TRACKING_QUOTA_REACHEDThe keyword quota for your tier is full.

DELETE /v1/account/addons/rank-tracking/keywords/{keyword_id}

Cost: Free

Remove a tracked keyword.

Auth: Bearer

ParameterInTypeRequiredDescription
keyword_idpathstringYesThe keyword id.

Request

bash
curl -X DELETE https://api.ai92.ai/v1/account/addons/rank-tracking/keywords/kw_01 \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{ "deleted": true, "id": "kw_01" }

Errors

StatusCodeWhen
404(keyword not found)Keyword does not exist or is not owned by the account.

Audit Log Exports

List and re-run audit-log CSV export jobs. To trigger a new export, use POST /v1/account/usage/export (see Usage); poll its status with GET /v1/account/usage/export/{job_id}.

GET /v1/account/audit/export

Cost: Free

List the account's audit-log export jobs (most recent first, up to 50).

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/account/audit/export \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
[
  {
    "id": "exp_01",
    "filters": { "from": "2026-06-01", "to": "2026-06-21" },
    "status": "completed",
    "requested_at": "2026-06-21T09:00:00Z",
    "completed_at": "2026-06-21T09:00:20Z",
    "result_url": "https://cdn.ai92.ai/exports/exp_01.csv",
    "result_expires_at": "2026-06-28T09:00:20Z",
    "row_count": 1284,
    "failure_reason": null
  }
]

POST /v1/account/audit/export/{job_id}/re-export

Cost: Free

Re-run a prior audit export with the same filters. Returns a new queued job.

Auth: Bearer

ParameterInTypeRequiredDescription
job_idpathstringYesThe id of a prior export job to re-run.

Request

bash
curl -X POST https://api.ai92.ai/v1/account/audit/export/exp_01/re-export \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "id": "exp_02",
  "filters": { "from": "2026-06-01", "to": "2026-06-21" },
  "status": "queued",
  "requested_at": "2026-06-21T10:00:00Z",
  "completed_at": null,
  "result_url": null,
  "result_expires_at": null,
  "row_count": null,
  "failure_reason": null
}

Errors

StatusCodeWhen
404(export job not found)Job does not exist or is not owned by the account.

API Keys

POST /v1/account/keys

Cost: Free

Generate a new API key. The plaintext key is shown once in the response.

Auth: Bearer · Returns 201 Created

FieldTypeRequiredDescription
namestringYesKey name. Length 1128.
kindstringNoproduction (default) or sandbox.
expires_in_daysinteger / nullNoExpiry. Range 1730.
ip_whiteliststring[]NoAllowed CIDRs. Default [].
daily_credit_limitinteger / nullNoPer-key daily limit (>= 1).
monthly_credit_limitinteger / nullNoPer-key monthly limit (>= 1).

Request

bash
curl https://api.ai92.ai/v1/account/keys \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"name": "CI key", "kind": "production", "expires_in_days": 90, "daily_credit_limit": 500}'

Response 201 Created

json
{
  "id": "key_01",
  "name": "CI key",
  "kind": "production",
  "prefix": "ai92_live",
  "last4": "9f2a",
  "plaintext_key": "ai92_live_9c0de…9f2a",
  "created_at": "2026-06-21T09:00:00Z",
  "expires_at": "2026-09-19T09:00:00Z",
  "ip_whitelist": [],
  "daily_credit_limit": 500,
  "monthly_credit_limit": null,
  "warning": "Store this key now. It will not be shown again."
}

GET /v1/account/keys

Cost: Free

List API keys (metadata only — never the plaintext key).

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/account/keys \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "keys": [
    {
      "id": "key_01", "name": "CI key", "kind": "production",
      "prefix": "ai92_live", "last4": "9f2a",
      "created_at": "2026-06-21T09:00:00Z", "expires_at": "2026-09-19T09:00:00Z",
      "last_used_at": "2026-06-21T09:10:00Z", "revoked_at": null,
      "ip_whitelist": [], "daily_credit_limit": 500, "monthly_credit_limit": null
    }
  ]
}

GET /v1/account/keys/{key_id}

Cost: Free

Get one API key's metadata (never the plaintext key).

Auth: Bearer

ParameterInTypeRequiredDescription
key_idpathstringYesThe key id.

Request

bash
curl https://api.ai92.ai/v1/account/keys/key_01 \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "id": "key_01",
  "name": "CI key",
  "kind": "production",
  "prefix": "ai92_live",
  "last4": "9f2a",
  "created_at": "2026-06-21T09:00:00Z",
  "expires_at": "2026-09-19T09:00:00Z",
  "last_used_at": "2026-06-21T09:10:00Z",
  "revoked_at": null,
  "ip_whitelist": [],
  "daily_credit_limit": 500,
  "monthly_credit_limit": null
}

Errors

StatusCodeWhen
404(key not found)Key does not exist or is not owned by the account.

PATCH /v1/account/keys/{key_id}

Cost: Free

Edit a key's name, allowlist, or spending limits.

Auth: Bearer

ParameterInTypeRequiredDescription
key_idpathstringYesThe key id.
namebodystring / nullNoNew name. Max length 128.
ip_whitelistbodystring[] / nullNoNew allowlist.
daily_credit_limitbodyinteger / nullNoNew daily limit (>= 0).
monthly_credit_limitbodyinteger / nullNoNew monthly limit (>= 0).

Request

bash
curl -X PATCH https://api.ai92.ai/v1/account/keys/key_01 \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"daily_credit_limit": 1000}'

Response 200 OK

json
{ "ok": true }

Errors

StatusCodeWhen
404NOT_FOUNDKey does not exist or is not owned by the account.

DELETE /v1/account/keys/{key_id}

Cost: Free

Revoke an API key.

Auth: Bearer · Returns 204 No Content

ParameterInTypeRequiredDescription
key_idpathstringYesThe key id.

Request

bash
curl -X DELETE https://api.ai92.ai/v1/account/keys/key_01 \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 204 No Content (empty body)

Errors

StatusCodeWhen
404NOT_FOUNDKey does not exist or is not owned by the account.

Usage

GET /v1/account/usage

Cost: Free

Usage history: daily aggregate credits plus a per-service breakdown.

Auth: Bearer

ParameterInTypeRequiredDescription
range_daysqueryintegerNoLook-back window. Default 30.
servicequerystring / nullNoFilter by service.

Request

bash
curl "https://api.ai92.ai/v1/account/usage?range_days=7" \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "range_days": 7,
  "service_filter": null,
  "daily_series": [ { "date": "2026-06-20", "credits": 120 } ],
  "service_breakdown": [ { "service": "contacts", "credits": 540, "count": 88 } ]
}

GET /v1/account/usage/log

Cost: Free

Paginated activity log.

Auth: Bearer

ParameterInTypeRequiredDescription
cursorquerystring / nullNoPagination cursor.
limitqueryintegerNoPage size. Default 50.
servicequerystring / nullNoFilter by service.
status_classquerystring / nullNo2xx, 4xx, or 5xx.

Request

bash
curl "https://api.ai92.ai/v1/account/usage/log?limit=2&status_class=2xx" \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "items": [
    {
      "request_id": "req_9a", "ts": "2026-06-21T08:55:00Z", "method": "POST",
      "endpoint": "/v1/contacts/reveal", "service": "contacts", "status": 200,
      "credits": 3, "latency_ms": 142, "trace_id": "tr_77", "backend_module": "module-H"
    }
  ],
  "next_cursor": "eyJvZmZzZXQiOjJ9"
}

POST /v1/account/usage/export

Cost: Free

Trigger an audit-log CSV export (async). Poll the returned job.

Auth: Bearer

FieldTypeRequiredDescription
sincedatetimeYesExport lower bound (ISO 8601).
untildatetime / nullNoExport upper bound.
include_credit_transactionsbooleanNoInclude credit transactions. Default true.
include_request_logbooleanNoInclude request log. Default true.

Request

bash
curl https://api.ai92.ai/v1/account/usage/export \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"since": "2026-06-01T00:00:00Z", "include_credit_transactions": true, "include_request_log": true}'

Response 200 OK

json
{
  "job_id": "5f2c0a91-…",
  "status": "queued",
  "poll_url": "/v1/account/usage/export/5f2c0a91-…"
}

GET /v1/account/usage/export/{job_id}

Cost: Free

Poll an audit-export job.

Auth: Bearer

ParameterInTypeRequiredDescription
job_idpathstringYesThe export job id.

Request

bash
curl https://api.ai92.ai/v1/account/usage/export/5f2c0a91-… \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "job_id": "5f2c0a91-…",
  "status": "completed",
  "result_url": "https://cdn.ai92.ai/exports/5f2c0a91.csv",
  "result_expires_at": "2026-06-22T09:00:00Z",
  "row_count": 4210,
  "error_message": null
}

Errors

StatusCodeWhen
404NOT_FOUNDJob does not exist or is not owned by the account.

Billing

POST /v1/billing/checkout

Cost: Free

Start a credit-package purchase via Stripe (proxied to module-a).

Auth: Bearer

FieldTypeRequiredDescription
package_codestring (enum)YesCredit package code.
success_urlURLYesRedirect on success.
cancel_urlURLYesRedirect on cancel.

Request

bash
curl https://api.ai92.ai/v1/billing/checkout \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"package_code": "GROWTH", "success_url": "https://app.ai92.ai/ok", "cancel_url": "https://app.ai92.ai/cancel"}'

Response 200 OK

json
{ "session_id": "cs_test_…", "url": "https://checkout.stripe.com/c/pay/cs_test_…" }

POST /v1/billing/checkout-custom

Cost: Free

Pay-as-you-go: start a Stripe Checkout for an arbitrary credit amount. module-a prices it at the floor pack tier and builds a Stripe price_data line item; on payment its webhook grants the credits. In the sandbox this returns a mock checkout URL and never charges.

Auth: Bearer

FieldTypeRequiredDescription
creditsintegerYesCredits to buy. Range 10001000000.
success_urlURLYesRedirect after a successful payment.
cancel_urlURLYesRedirect if the customer cancels.

Request

bash
curl https://api.ai92.ai/v1/billing/checkout-custom \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"credits": 25000, "success_url": "https://app.acme.com/ok", "cancel_url": "https://app.acme.com/cancel"}'

Response 200 OK

json
{ "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_…" }

In the sandbox the response is { "checkout_url": "https://checkout.stripe.com/sandbox/mock", "sandbox": true }.


GET /v1/billing/invoices

Cost: Free

List invoices (proxied to module-a).

Auth: Bearer

ParameterInTypeRequiredDescription
pagequeryintegerNo1-based page number. Default 1.
page_sizequeryintegerNoItems per page. Default 50.

Unlike the cursor-paginated list endpoints, GET /v1/billing/invoices uses offset pagination: pass page / page_size and read total / page / page_size back.

Request

bash
curl "https://api.ai92.ai/v1/billing/invoices?page=1&page_size=10" \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "total": 1,
  "page": 1,
  "page_size": 10,
  "items": [ { "id": "in_01", "amount": 9900, "currency": "usd", "created_at": "2026-06-01T00:00:00Z" } ]
}

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

Cost: Free

Download an invoice PDF (proxied to module-a).

Auth: Bearer

ParameterInTypeRequiredDescription
invoice_idpathstringYesThe invoice id.

Request

bash
curl https://api.ai92.ai/v1/billing/invoices/in_01/pdf \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{ "download_url": "https://cdn.ai92.ai/invoices/in_01.pdf" }

POST /v1/billing/subscription

Cost: Free

Start a Stripe Checkout for a hybrid subscription tier. On payment, the billing webhook activates the subscription and grants the bundled credits automatically.

Auth: Bearer

FieldTypeRequiredDescription
tierstring (enum)Yespro_sub, business_sub, or enterprise_sub.
success_urlURLYesRedirect on success.
cancel_urlURLYesRedirect on cancel.

Request

bash
curl -X POST https://api.ai92.ai/v1/billing/subscription \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"tier": "pro_sub", "success_url": "https://app.acme.com/ok", "cancel_url": "https://app.acme.com/cancel"}'

Response 200 OK

json
{ "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_…" }

In the sandbox the response is { "checkout_url": "https://checkout.stripe.com/sandbox/mock", "sandbox": true } and nothing is charged.


GET /v1/billing/subscription

Cost: Free

Current subscription plus the hybrid tier catalog (the same snapshot the dashboard subscription panel renders).

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/billing/subscription \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "current": {
    "tier": "pro_sub",
    "status": "active",
    "current_period_end": "2026-08-01T00:00:00Z",
    "bundled_credits_per_period": 4000,
    "cancel_at_period_end": false
  },
  "available_tiers": [
    { "code": "pro_sub", "price_usd_cents": 7900, "bundled_credits_per_period": 4000, "bonus_pct": 20 },
    { "code": "business_sub", "price_usd_cents": 27900, "bundled_credits_per_period": 18000, "bonus_pct": 20 },
    { "code": "enterprise_sub", "price_usd_cents": 149900, "bundled_credits_per_period": 130000, "bonus_pct": 20 }
  ]
}

current is null-ish (tier: null) when the account has no subscription. Each period the grant is the bundle plus the renewal bonus (bonus_pct) — e.g. 4,000 + 20% = 4,800 credits on Pro.


POST /v1/billing/addons/{kind}

Cost: Free

Start a Stripe Checkout for a monthly add-on. On payment, the billing webhook activates the add-on entitlement automatically.

Auth: Bearer

ParameterInTypeRequiredDescription
kindpathstring (enum)YesAdd-on kind: mass_mail or rank_tracking.
success_urlbodyURLYesRedirect on success.
cancel_urlbodyURLYesRedirect on cancel.

Request

bash
curl -X POST https://api.ai92.ai/v1/billing/addons/mass_mail \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"success_url": "https://app.acme.com/ok", "cancel_url": "https://app.acme.com/cancel"}'

Response 200 OK

json
{ "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_…" }

In the sandbox the response is { "checkout_url": "https://checkout.stripe.com/sandbox/mock", "sandbox": true } and nothing is charged.


Webhooks

Allowed event types: contact.verified, campaign.sent, campaign.reply, campaign.open, campaign.click, campaign.bounce, visitor.identified, review.new, credits.low, seo.alert, key.expiring, account.inactivity_warning, account.read_only, account.reactivated, sla.violation.

Subscribing to any name outside this list returns 422 UNKNOWN_EVENT_TYPE and the endpoint is not created. There is no job.completed/scan.completed event — async job and scan results are polled, not delivered by webhook (see Async Jobs).

POST /v1/webhooks

Cost: Free

Create a webhook endpoint. The signing secret is shown once.

Auth: Bearer · Returns 201 Created

FieldTypeRequiredDescription
urlURLYesDestination URL.
descriptionstring / nullNoDescription. Max length 255.
eventsstring[]NoSubscribed events (must be from the allowed list; at least one required). Default [].

Request

bash
curl https://api.ai92.ai/v1/webhooks \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://hooks.acme.com/ai92", "description": "Prod hook", "events": ["campaign.sent", "credits.low"]}'

Response 201 Created

json
{
  "id": "wh_01",
  "url": "https://hooks.acme.com/ai92",
  "description": "Prod hook",
  "events": ["campaign.sent", "credits.low"],
  "active": true,
  "created_at": "2026-06-21T09:00:00Z",
  "secret": "whsec_…",
  "warning": "Store this signing secret now. It will not be shown again."
}

Errors

StatusCodeWhen
422VALIDATION_ERRORUnknown event types, or no events provided.
503WEBHOOKS_UNAVAILABLEWebhook signing not configured on this environment.

GET /v1/webhooks

Cost: Free

List webhook endpoints.

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/webhooks \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "endpoints": [
    {
      "id": "wh_01", "url": "https://hooks.acme.com/ai92", "description": "Prod hook",
      "events": ["campaign.sent", "credits.low"], "active": true,
      "last_success_at": "2026-06-21T08:00:00Z", "last_failure_at": null,
      "created_at": "2026-06-21T09:00:00Z"
    }
  ]
}

GET /v1/webhooks/{endpoint_id}

Cost: Free

Get one webhook endpoint (metadata + last success/failure timestamps; never the signing secret, which is shown once at creation).

Auth: Bearer

ParameterInTypeRequiredDescription
endpoint_idpathstringYesThe webhook endpoint id.

Request

bash
curl https://api.ai92.ai/v1/webhooks/wh_01 \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "id": "wh_01",
  "url": "https://hooks.acme.com/ai92",
  "description": "Prod hook",
  "events": ["campaign.sent", "credits.low"],
  "active": true,
  "last_success_at": "2026-06-21T09:10:00Z",
  "last_failure_at": null,
  "created_at": "2026-06-21T09:00:00Z"
}

Errors

StatusCodeWhen
404(endpoint not found)Endpoint does not exist or is not owned by the account.

DELETE /v1/webhooks/{endpoint_id}

Cost: Free

Delete a webhook endpoint.

Auth: Bearer · Returns 204 No Content

ParameterInTypeRequiredDescription
endpoint_idpathstringYesThe endpoint id.

Request

bash
curl -X DELETE https://api.ai92.ai/v1/webhooks/wh_01 \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 204 No Content (empty body)

Errors

StatusCodeWhen
404NOT_FOUNDEndpoint does not exist or is not owned by the account.

POST /v1/webhooks/{endpoint_id}/replay

Cost: Free

Replay events to an endpoint over a date range. Generates fresh deliveries.

Auth: Bearer

ParameterInTypeRequiredDescription
endpoint_idpathstringYesThe endpoint id.
sincebodydatetimeYesReplay lower bound.
untilbodydatetime / nullNoReplay upper bound.
event_typesbodystring[]NoRestrict to specific event types. Default [].

Request

bash
curl https://api.ai92.ai/v1/webhooks/wh_01/replay \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"since": "2026-06-20T00:00:00Z", "event_types": ["campaign.sent"]}'

Response 200 OK

json
{ "replay_count": 42, "status": "queued" }

GET /v1/webhooks/{endpoint_id}/dlq

Cost: Free

List dead-letter deliveries for an endpoint.

Auth: Bearer

ParameterInTypeRequiredDescription
endpoint_idpathstringYesThe endpoint id.
limitqueryintegerNoPage size. Default 50.
cursorquerystring / nullNoPagination cursor.

Request

bash
curl "https://api.ai92.ai/v1/webhooks/wh_01/dlq?limit=20" \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "deliveries": [
    {
      "id": "dlq_5", "event_id": "ev_9", "event_type": "campaign.sent",
      "attempts": 6, "last_status_code": 500, "last_error": "upstream timeout",
      "last_attempt_at": "2026-06-21T07:00:00Z"
    }
  ],
  "next_cursor": null
}

POST /v1/webhooks/{endpoint_id}/dlq/redrive

Cost: Free

Re-dispatch dead-letter deliveries. Unlike /replay, this re-tries the same delivery rows, so handlers see the same X-AI92-Delivery-Id and can dedupe naturally.

Auth: Bearer

ParameterInTypeRequiredDescription
endpoint_idpathstringYesThe endpoint id.
delivery_idsbodystring[]NoSpecific delivery ids. Default []. Max 500.
max_countbodyintegerNoMax deliveries to redrive. Default 100. Range 1500.

Request

bash
curl https://api.ai92.ai/v1/webhooks/wh_01/dlq/redrive \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"delivery_ids": ["dlq_5"], "max_count": 100}'

Response 200 OK

json
{ "endpoint_id": "wh_01", "redriven_count": 1, "status": "queued" }

Errors

StatusCodeWhen
404NOT_FOUNDEndpoint does not exist or is not owned by the account.

OAuth Apps

Register and manage your own OAuth 2.0 clients (the same apps you see in the OAuth panel). These let you issue OAuth access tokens for your account instead of static API keys. This is the customer-facing surface under /v1/oauth/apps; it is distinct from the operator-only admin OAuth router.

Available scopes: contacts:read, contacts:write, campaigns:read, campaigns:create, campaigns:send, seo:read, markets:read, reviews:read, reviews:reply, cloud:read, cloud:write, webhooks:manage, account:read, account:write, offline_access.

GET /v1/oauth/apps

Cost: Free

List the account's OAuth apps with per-app token counts and last-used timestamp.

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/oauth/apps \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
[
  {
    "client_id": "cli_3f9a…",
    "name": "Acme Integration",
    "description": "Server-to-server sync",
    "redirect_uris": ["https://app.acme.com/oauth/callback"],
    "scopes": ["contacts:read", "campaigns:read", "offline_access"],
    "created_at": "2026-06-10T12:00:00Z",
    "suspended_at": null,
    "tokens_issued_count": 4,
    "active_tokens_count": 2,
    "last_used_at": "2026-06-21T08:00:00Z"
  }
]

POST /v1/oauth/apps

Cost: Free

Register a new OAuth app. The client_secret is returned once in the response — store it securely.

Auth: Bearer · Returns 201 Created

FieldTypeRequiredDescription
namestringYesApp name. Length 1128.
descriptionstring / nullNoDescription. Max length 1024.
redirect_urisstring[]NoAllowed OAuth redirect URIs. Default [].
scopesstring[]NoRequested scopes (must be from the allowed list). Default [].

Request

bash
curl https://api.ai92.ai/v1/oauth/apps \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme Integration", "redirect_uris": ["https://app.acme.com/oauth/callback"], "scopes": ["contacts:read", "offline_access"]}'

Response 201 Created

json
{
  "app": {
    "client_id": "cli_3f9a…",
    "name": "Acme Integration",
    "description": null,
    "redirect_uris": ["https://app.acme.com/oauth/callback"],
    "scopes": ["contacts:read", "offline_access"],
    "created_at": "2026-06-21T09:00:00Z",
    "suspended_at": null,
    "tokens_issued_count": 0,
    "active_tokens_count": 0,
    "last_used_at": null
  },
  "client_secret": "s3cr3t_…"
}

Errors

StatusCodeWhen
400INVALID_SCOPEOne or more requested scopes are not in the allowed list.

DELETE /v1/oauth/apps/{client_id}

Cost: Free

Revoke (suspend) an OAuth app. The app is suspended and all of its outstanding tokens are revoked.

Auth: Bearer

ParameterInTypeRequiredDescription
client_idpathstringYesThe OAuth client id to revoke.

Request

bash
curl -X DELETE https://api.ai92.ai/v1/oauth/apps/cli_3f9a… \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{ "client_id": "cli_3f9a…", "revoked": true }

Errors

StatusCodeWhen
404(app not found)App does not exist or is not owned by the account.

Brands

Brand onboarding turns an account into one or more operational brands across the fleet. The first brand is free; each additional sub-brand costs brand_create_cost credits (charged post-success). Sandbox onboarding is always free.

POST /v1/brands

Cost: Free for the first brand; configured credit cost for each additional sub-brand (sandbox always free)

Register (or link) a brand. Creates the brand in module-a (the fleet source of truth) and persists the 923 brand row.

Auth: Bearer

FieldTypeRequiredDescription
namestringYesBrand name. Length 1200.
domainstring / nullNoBrand domain. Max length 255. Enables SEO/AI-visibility/markets readiness.
logo_urlstring / nullNoLogo URL. Max length 1024.
brand_colorsobject / nullNoBrand color palette.
tonestring / nullNoBrand tone. Max length 64.
link_existing_brand_idstring / nullNoLink an existing module-a brand instead of creating one. Max length 128.

Request

bash
curl https://api.ai92.ai/v1/brands \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme Corp", "domain": "acme.com", "tone": "confident"}'

Response 200 OK

json
{
  "brand_id": "b1f0…",
  "canonical_brand_id": "acme",
  "name": "Acme Corp",
  "domain": "acme.com",
  "status": "active",
  "readiness": {
    "creative": true, "build_campaign": true, "seo": true, "ai_visibility": true,
    "markets": true, "intent": false, "contacts": false, "reviews": false
  },
  "created_at": "2026-06-21T09:00:00Z",
  "credits_charged": 0
}

Errors

StatusCodeWhen
402INSUFFICIENT_CREDITSSub-brand created upstream but balance too low to finalize billing.

GET /v1/brands

Cost: Free

List the account's brands.

Auth: Bearer

Request

bash
curl https://api.ai92.ai/v1/brands \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "brands": [
    { "brand_id": "b1f0…", "canonical_brand_id": "acme", "name": "Acme Corp", "domain": "acme.com", "status": "active", "readiness": {}, "created_at": "2026-06-21T09:00:00Z" }
  ],
  "count": 1
}

GET /v1/brands/{brand_id}

Cost: Free

Get a single brand.

Auth: Bearer

ParameterInTypeRequiredDescription
brand_idpathstringYesThe brand id (UUID).

Request

bash
curl https://api.ai92.ai/v1/brands/b1f0… \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{ "brand_id": "b1f0…", "canonical_brand_id": "acme", "name": "Acme Corp", "domain": "acme.com", "status": "active", "readiness": {}, "created_at": "2026-06-21T09:00:00Z" }

Errors

StatusCodeWhen
404BRAND_NOT_FOUNDBrand does not exist or is not owned by the account.

GET /v1/brands/{brand_id}/readiness

Cost: Free

Per-product readiness and what is still missing to unlock each product.

Auth: Bearer

ParameterInTypeRequiredDescription
brand_idpathstringYesThe brand id (UUID).

Request

bash
curl https://api.ai92.ai/v1/brands/b1f0…/readiness \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "brand_id": "b1f0…",
  "readiness": { "creative": true, "seo": true, "intent": false, "contacts": false, "reviews": false },
  "next_steps": {
    "intent": "POST /v1/brands/{id}/tracking and install the pixel",
    "contacts": "POST /v1/brands/{id}/icp",
    "reviews": "POST /v1/brands/{id}/connections/gbp"
  }
}

Errors

StatusCodeWhen
404BRAND_NOT_FOUNDBrand not owned by the account.

POST /v1/brands/{brand_id}/icp

Cost: Free

Set the brand's ideal-customer profile — enables Contact Finder.

Auth: Bearer

ParameterInTypeRequiredDescription
brand_idpathstringYesThe brand id (UUID).
industriesbodystring[] / nullNoTarget industries.
titlesbodystring[] / nullNoTarget job titles.
geosbodystring[] / nullNoTarget geographies.
company_sizesbodystring[] / nullNoTarget company sizes.

Request

bash
curl https://api.ai92.ai/v1/brands/b1f0…/icp \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"industries": ["software"], "titles": ["VP Marketing"], "geos": ["US"]}'

Response 200 OK

json
{ "brand_id": "b1f0…", "readiness": { "contacts": true } }

Errors

StatusCodeWhen
404BRAND_NOT_FOUNDBrand not owned by the account.

POST /v1/brands/{brand_id}/seo

Cost: Free

Set SEO context (domain, keywords, competitors) — enables SEO, AI-Visibility, and Markets.

Auth: Bearer

ParameterInTypeRequiredDescription
brand_idpathstringYesThe brand id (UUID).
domainbodystringYesBrand domain. Length 1255.
keywordsbodystring[] / nullNoSeed keywords.
competitorsbodystring[] / nullNoCompetitor domains.

Request

bash
curl https://api.ai92.ai/v1/brands/b1f0…/seo \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"domain": "acme.com", "keywords": ["crm"], "competitors": ["rival.com"]}'

Response 200 OK

json
{ "brand_id": "b1f0…", "readiness": { "seo": true, "ai_visibility": true, "markets": true } }

Errors

StatusCodeWhen
404BRAND_NOT_FOUNDBrand not owned by the account.

POST /v1/brands/{brand_id}/tracking

Cost: Free

Get the tracking pixel — enables Who-Is-Searching once traffic is detected.

Auth: Bearer

ParameterInTypeRequiredDescription
brand_idpathstringYesThe brand id (UUID).

Request

bash
curl -X POST https://api.ai92.ai/v1/brands/b1f0…/tracking \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "brand_id": "b1f0…",
  "pixel_id": "ai92px_b1f0a2c3d4e5f607",
  "snippet": "<script async src=\"https://px.ai92.ai/p.js\" data-ai92-pixel=\"ai92px_b1f0a2c3d4e5f607\"></script>",
  "note": "intent/Who-Is-Searching activates once we detect traffic from this pixel."
}

Errors

StatusCodeWhen
404BRAND_NOT_FOUNDBrand not owned by the account.

POST /v1/brands/{brand_id}/connections/gbp

Cost: Free

Start a Google Business Profile connection — enables Reviews. The customer completes Google OAuth out of band.

Auth: Bearer

ParameterInTypeRequiredDescription
brand_idpathstringYesThe brand id (UUID).
location_idsbodystring[] / nullNoGBP location ids to connect.

Request

bash
curl https://api.ai92.ai/v1/brands/b1f0…/connections/gbp \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"location_ids": ["loc_7"]}'

Response 200 OK

json
{
  "brand_id": "b1f0…",
  "oauth_status": "pending",
  "authorize_url": "/v1/oauth/google/start?brand_id=b1f0…",
  "note": "Complete Google authorization to enable Reviews/GBP."
}

Errors

StatusCodeWhen
404BRAND_NOT_FOUNDBrand not owned by the account.

POST /v1/brands/{brand_id}/products

Cost: Free

Add a product (optional) — enables creative image→image generation.

Auth: Bearer

ParameterInTypeRequiredDescription
brand_idpathstringYesThe brand id (UUID).
namebodystringYesProduct name. Length 1255.
product_urlbodystring / nullNoProduct page URL. Max length 1024.
image_urlbodystring / nullNoProduct image URL. Max length 1024.
attributesbodyobject / nullNoArbitrary product attributes.

Request

bash
curl https://api.ai92.ai/v1/brands/b1f0…/products \
  -H "Authorization: Bearer ai92_test_51a9c0de…" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme CRM Pro", "product_url": "https://acme.com/pro", "image_url": "https://cdn.acme.com/pro.png"}'

Response 200 OK

json
{ "brand_id": "b1f0…", "status": "product_added" }

Errors

StatusCodeWhen
404BRAND_NOT_FOUNDBrand not owned by the account.

Polling async jobs

Several services (creative, seo/ai-visibility scans, usage export) return a job_id. Poll any async job at:

GET /v1/jobs/{job_id}

Cost: Free

Return the status (and, when finished, the result) of an async job. Returns 404 NOT_FOUND for unknown ids and ids owned by another tenant.

Auth: Bearer

ParameterInTypeRequiredDescription
job_idpathstringYesThe job id returned by the originating endpoint.

Request

bash
curl https://api.ai92.ai/v1/jobs/f_7c1d0a92… \
  -H "Authorization: Bearer ai92_test_51a9c0de…"

Response 200 OK

json
{
  "job_id": "f_7c1d0a92…",
  "status": "completed",
  "service": "creative",
  "credits_reserved": 15,
  "result": { "asset_id": "ast_nl1", "url": "https://cdn.ai92.ai/ast_nl1.png" }
}

Errors

StatusCodeWhen
404NOT_FOUNDJob not found or not owned by the account.