Authentication
Every authenticated AskBiz API call carries your key in the x-api-key header. This page covers the mechanics that apply across endpoints — key modes, Idempotency-Key, and rate limits — so each individual reference page doesn't have to repeat them.
How authentication works
Send your key in an x-api-key header on every request to an authenticated endpoint — not Authorization: Bearer. There’s no OAuth flow and no session cookie involved for programmatic API calls. GET /api/v1/pricing is the one exception: it’s fully public and needs no key at all. Webhook management (/api/v1/webhooks) is the other exception in the opposite direction — it’s a dashboard-only, session-authenticated account setting, never called with an x-api-key by a third-party server. See the webhooks guide for that distinction.
curl -X POST https://askbiz.co/api/v1/ask \
-H "x-api-key: abz_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"question": "What were my top sellers this week?"
}'Create and manage keys from the Keys page in your developer.askbiz.co dashboard. Treat a key like a password — anyone who has it can act as you against every endpoint it’s valid for.
Every key is also either test (abz_test_…) or live (abz_live_…) — fixed at creation, visible in the prefix itself. A test key is the safe default for a new key: /scan, /whatsapp/send, and /charges all return realistic canned responses on a test key with nothing real happening. See Build safely with a sandbox key.
Account mode vs generic mode
Every key is created in one of two modes, chosen when you generate it. The mode changes what an endpoint does with your request, not just what it’s allowed to call.
| Mode | What it is | What changes |
|---|---|---|
account | Tied to a real AskBiz business — your own connected account. | /api/v1/ask automatically pulls your business type, currency, region, and latest uploaded dataset columns — any context you pass in the request body is ignored. Required for /api/v1/whatsapp/send, which returns a 403 to a generic-mode key. |
generic | Not tied to a real AskBiz business — for integrating AskBiz into someone else’s product. | You must supply context yourself on /api/v1/ask calls, since there’s no connected account for it to read from. Cannot call /api/v1/whatsapp/send — a generic key has no tie to a real business, so it deliberately can’t be used as an open message-blasting gateway. |
Idempotency-Key
Send an Idempotency-Key header — any client-generated string, such as a UUID — on a POST to /api/v1/scan or /api/v1/whatsapp/send. If you retry with the same key value — for example after a network timeout where you don’t know if the first attempt landed — the API returns the exact original response instead of re-running the underlying action. A retry never sends a second real WhatsApp message or runs a second vision call, and never double-charges. This is the same header-name convention Stripe uses.
Without an Idempotency-Key, every request is treated as independent — a retry is a brand-new, separately billable call.
curl -X POST https://askbiz.co/api/v1/whatsapp/send \
-H "x-api-key: abz_live_your_key_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7c4f1a2e-9d3b-4e6a-8f21-1b5c9a0d3e7f" \
-d '{
"phone": "+254712345678",
"template": "receipt",
"text": "Receipt #1042 — Total KES 160. Thank you for your purchase."
}'
# If this call times out and you don't know whether it landed, retry with
# the exact same Idempotency-Key value. You get back the original response
# instead of a second WhatsApp message and a second 2¢ debit.| Endpoint | Idempotency-Key |
|---|---|
POST /api/v1/scan | Supported |
POST /api/v1/whatsapp/send | Supported |
POST /api/v1/ask | Not supported — every call is independent. |
POST /api/v1/connections | Not supported. |
POST /api/v1/charges | Not supported. |
Rate limits and monthly quota
Two separate numeric limits apply to your key, enforced independently: a per-minute rate limit and a monthly quota. Both come from your plan.
| Plan | Monthly quota | Per-minute limit |
|---|---|---|
| free | 100 | 5 |
| growth | 10,000 | 60 |
| business | Unlimited | 120 |
Every /api/v1/* endpoint returns your live per-minute standing on every response, success or failure, backed by a durable per-key counter rather than an in-memory guess that could differ between serverless instances:
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
{ "success": true }The monthly quota is enforced separately from the per-minute limit and, when exceeded, returns a 429 whose body includes plan, limit, and used so you know exactly where you stand.
Error responses
Every error response is JSON with at least an error string field. Some errors carry extra context specific to that failure — documented per-endpoint on each API reference page — rather than one universal schema. For example, insufficient credits (402, on billed endpoints only) includes required_cents and a topup URL.
| Status | Meaning |
|---|---|
| 401 | Missing or invalid x-api-key. |
| 403 | The key has been disabled — re-enable it from the Keys page in your dashboard. Or, on an endpoint that requires it (like /api/v1/whatsapp/send), the key is in generic mode. |
| 429 | Per-minute rate limit or monthly quota exceeded. A monthly-quota 429 includes plan, limit, and used in the body. |
{
"error": "Invalid or missing API key"
}Authentication FAQ
What happens if my API key is compromised?+
Disable it immediately from the Keys page in your developer.askbiz.co dashboard, then create a new key to replace it. There is no key-rotation feature — disabling stops the compromised key from authenticating anything, and every call made with it returns a 403 until you re-enable it (which you shouldn’t do for a key you no longer trust) or simply leave it disabled and switch your integration to the new key.
Which endpoints support Idempotency-Key?+
Only POST /api/v1/scan and POST /api/v1/whatsapp/send. POST /api/v1/ask, POST /api/v1/connections, and POST /api/v1/charges don’t support it — retrying those is always treated as a brand-new request, so build your own duplicate-prevention if that matters for your integration.
How is the per-minute limit enforced — can it be bypassed by hitting different servers?+
No. The counter is a durable, atomic database counter keyed by your API key, not an in-memory count on whichever server happened to handle the request. Every request against a given key — regardless of which serverless instance processes it — increments the same counter, so the X-RateLimit-Remaining header is always accurate.
Do I need to send an Idempotency-Key on every request?+
It’s optional but strongly recommended on /api/v1/scan and /api/v1/whatsapp/send, especially around network calls that might time out. Without one, a retry — even an accidental one — is billed as a brand-new call; with one, retrying with the same key value returns the original result instead.