Az AI92 elindult – globális soft launchunk zajlik: a teljes platform világszerte nyitva áll az első 30 napban.
Dokumentációs menü

Ezek a fejlesztői dokumentumok jelenleg csak angol nyelven érhetők el. A kód és az API viselkedése minden régióban azonos.

Authentication

The AI92 API supports two authentication schemes, both presented as a bearer token in the Authorization header:

  1. API keys — for your own server-to-server integrations. Simplest; start here.
  2. OAuth 2.0 — for apps that act on behalf of other AI92 users (third-party integrations, marketplace apps).

The gateway routes by token shape automatically: a token starting with ai92_live_ or ai92_test_ is treated as an API key; a token in header.payload.signature (JWT) form is treated as an OAuth access token.

http
Authorization: Bearer ai92_live_aBcD1234XXXXXXXXXXXXXXXXXXXXXXXX

A missing or malformed header returns 401 AUTHENTICATION_REQUIRED. An unrecognized token returns 401 INVALID_API_KEY.


API keys

Prefixes

PrefixEnvironmentSpends credits?
ai92_live_ProductionYes
ai92_test_SandboxNo — never

The prefix is the switch. The same code, hitting the same host, runs against sandbox or production purely based on which key you send. See Sandbox.

How keys are stored

Keys are generated as <prefix><random> and the plaintext is returned exactly once, at creation. AI92 stores only a SHA-256 hash of the key plus a non-secret display prefix (e.g. ai92_live_aBcD1234) and the last four characters. We cannot recover a lost key — if you lose it, rotate.

Creating a key

Once you have one key, you can mint more programmatically:

bash
curl -X POST https://api.ai92.ai/v1/account/keys \
  -H "Authorization: Bearer ai92_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "production-worker",
    "kind": "production",
    "expires_in_days": 365,
    "daily_credit_limit": 5000,
    "monthly_credit_limit": 100000,
    "ip_whitelist": ["203.0.113.0/24"]
  }'

The response includes plaintext_key once:

json
{
  "id": "9b1c...",
  "name": "production-worker",
  "kind": "production",
  "prefix": "ai92_live_aBcD1234",
  "last4": "9f2k",
  "plaintext_key": "ai92_live_aBcD1234...9f2k",
  "expires_at": "2027-06-21T00:00:00Z",
  "daily_credit_limit": 5000,
  "monthly_credit_limit": 100000,
  "warning": "This is the only time the full key will be shown. Store it securely."
}

Per-key controls

Each key can carry independent guardrails — useful for isolating a worker, a customer, or an environment:

  • expires_in_days — auto-expiry. After expiry, the key returns 401 EXPIRED_API_KEY.
  • ip_whitelist — a list of CIDRs. Requests from outside them return 403 IP_NOT_ALLOWED. The first hop of X-Forwarded-For is trusted (behind the AI92 edge).
  • daily_credit_limit / monthly_credit_limit — per-key spending caps (0 = unlimited). Exceeding them returns 402 KEY_SPENDING_LIMIT while the rest of your account keeps working.

Edit these later with PATCH /v1/account/keys/{key_id}.

Rotation

Keys never auto-rotate. To rotate: create a new key, deploy it, then revoke the old one with DELETE /v1/account/keys/{key_id}. Revocation is immediate — a revoked key returns 401 INVALID_API_KEY on its very next use. Rotate on a schedule (90 days is a good default), on staff changes, and immediately on any suspected leak.

Security rules

  • Never embed a key in client-side code (browser JS, mobile bundles, public repos). Keys are full-account bearer credentials. Anything reachable by a browser will leak. Call AI92 from your server and proxy to your front end.
  • Prefer scoped, IP-restricted, credit-capped keys for each workload over one omnipotent key.
  • Store keys in a secret manager, not in .env committed to git.
  • If a key leaks, revoke first, investigate second.

OAuth 2.0

Use OAuth when your app needs to call AI92 on behalf of an AI92 user who is not you — for example a third-party tool a customer connects to their AI92 account. The user grants your app specific scopes; you receive an access token (a signed JWT) that grants only those scopes.

API keys grant all scopes for your account. OAuth tokens grant a subset of scopes for another account.

Endpoints

EndpointMethodPurpose
/v1/oauth/authorizeGETAuthorization Code consent screen
/v1/oauth/tokenPOSTExchange code → tokens; refresh tokens
/v1/oauth/introspectPOSTCheck whether a token is active
/v1/oauth/revokePOSTRevoke an access or refresh token
/v1/.well-known/jwks.jsonGETPublic signing keys (verify tokens)
/v1/.well-known/openid-configurationGETOIDC discovery document
/v1/oauth/userinfoGETUser profile, scoped to the grant

Authorization Code flow with PKCE

PKCE (S256) is required for public clients and recommended for all. The flow:

1. Generate a PKCE verifier + challenge, then redirect the user to consent:

https://api.ai92.ai/v1/oauth/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.com/callback
  &scope=contacts:read%20contacts:write%20offline_access
  &code_challenge=BASE64URL_SHA256_OF_VERIFIER
  &code_challenge_method=S256
  &state=RANDOM_CSRF_TOKEN

Supported response_type is code. Requesting an unknown scope returns invalid_scope; omitting a required code_challenge returns code_challenge_required.

2. Exchange the returned code for tokens:

bash
curl -X POST https://api.ai92.ai/v1/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=authorization_code \
  -d code=THE_CODE_FROM_CALLBACK \
  -d redirect_uri=https://yourapp.com/callback \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d code_verifier=YOUR_PKCE_VERIFIER
json
{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "eyJ...",
  "scope": "contacts:read contacts:write offline_access"
}

Access tokens live 1 hour. Refresh tokens live 90 days and are only issued when offline_access is in the granted scope.

3. Refresh when the access token expires:

bash
curl -X POST https://api.ai92.ai/v1/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=refresh_token \
  -d refresh_token=YOUR_REFRESH_TOKEN \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET

4. Call the API with the access token exactly like an API key:

bash
curl "https://api.ai92.ai/v1/contacts/search?q=saas+founder&country=US" \
  -H "Authorization: Bearer eyJ..."

Revocation is real-time

POST /v1/oauth/revoke invalidates a token immediately — the gateway checks each access token against the revocation table on every request, so a revoked or stolen JWT stops working at once rather than lingering until its TTL.

Token verification

Verify tokens offline against the JWKS at /v1/.well-known/jwks.json (RS256). Keys rotate roughly every 30 days; the previous key stays published in the JWKS for a 30-day grace window, so cache the JWKS and refresh it on an unknown kid.

Scopes

ScopeGrants
contacts:readRead contacts
contacts:writeReveal & enrich contacts
campaigns:readRead campaigns
campaigns:createCreate campaign objects
campaigns:sendSend campaign messages
seo:readRead SEO data
markets:readRead market analytics
reviews:readRead Google Reviews
reviews:replyReply to Google Reviews
cloud:readRead cloud storage
cloud:writeWrite cloud storage
webhooks:manageManage webhooks
account:readRead account info
account:writeModify account settings (e.g. auto-recharge)
offline_accessIssue refresh tokens

A token missing a scope required by an endpoint returns 403 FORBIDDEN_SCOPE.


Which should I use?

If you are…Use
Building your own backend integrationAPI key (ai92_live_)
TestingSandbox API key (ai92_test_)
Building an app that other AI92 users connectOAuth 2.0 with PKCE
Acting only within your own accountAPI key — it grants all scopes, no flow needed