Developers

Developer documentation

Send WhatsApp messages, place voice calls, have an AI voice agent call your customers, verify customers over a call and receive signed events, all from your own code.

WhatsApp base URL
https://app.agentive.co.in/api/v1
Voice base URL
https://voice.agentive.co.in/api/public/v1
Webhook payload version
2026-06-01

Products

Every reference has authentication, request and response shapes, error codes and copy-ready samples.

OpenAPI specification

Getting started

Three steps from a new account to a live request.

  1. 1

    Create an account

    Sign up for Agentive. The WhatsApp API is issued from the Chat dashboard and the voice APIs from the Voice dashboard, so start with the product you are integrating.

  2. 2

    Get your credentials

    Generate credentials in the dashboard. Each reference explains where to find them and which headers to send on every request.

  3. 3

    Make your first request

    Copy the quick start for your product, replace the placeholders, and send one message or place one call to your own number.

Platform conventions

Agentive ships two API families: the Voice APIs (Voice Broadcast, AI Voice Agent, Voice OTP and telephony webhooks) and the WhatsApp Business API. They share a brand, a dashboard account and a set of habits, but they are separate products and they do not agree on everything. This section is the one place that says what is common and, where they differ, exactly how.

Base URLs

Voice APIsWhatsApp Business API
Base URLhttps://voice.agentive.co.in/api/public/v1https://app.agentive.co.in/api/v1
CoversVoice Broadcast, AI Voice Agent, Voice OTP and the endpoints webhook events point back at. All of them share one base, one credential pair and one envelope.Template sends for one API campaign. Issued and managed from the Chat dashboard.
TransportHTTPS only, JSON in and JSON out.HTTPS only, JSON in and JSON out.

Authentication

Voice APIsWhatsApp Business API
CredentialOne publishable key (pk_live_...) and one secret (sk_live_...) per account.One token (agcamp_...) per API campaign, so a leaked token can only send that campaign.
How to send itx-api-key and x-api-secret headers, or HTTP Basic with the publishable key as the username and the secret as the password.Authorization: Bearer <token>.
ScopeAccount-wide. Every endpoint on the Voice base accepts it.Campaign-wide. The template and number are fixed on the campaign.
Treat asBoth keys are confidential. The publishable key names your account to anyone who holds it, so keep it with the secret, on your server only.A secret. Keep it on your server only.
RotationFrom the API Access tab of the Voice dashboard. The old secret stops working at once.From the campaign page in the Chat dashboard. The old token stops working at once.

Error envelope

Voice APIsWhatsApp Business API
Shape{ status, code: number, error_code: string, error, details, unique_id, reference_id }{ error, code: string, details: object }
What to branch onerror_code. The numeric code mirrors the HTTP status and stays for compatibility.code, which is itself the machine string.
Human sentencedetails, repeated in error so a handler written for the WhatsApp shape reads a Voice error too.error.
Extra contextNamed fields beside the envelope (lines, lines_in_use, attempts_left, retry_after_sec, balance_inr).A details object (missing, retryAfter, meta, validation).

401 and 403

Voice APIsWhatsApp Business API
401Credentials missing, unknown, or rejected. The status never confirms whether a key exists.Token missing or wrong.
403Credentials accepted, but the account is not active or the product is not enabled.Token accepted, but the campaign is not live or the number is not connected.
404Not found, or not yours. A foreign id is never a 403, because that would confirm it exists.Not found, or not yours. Same rule.

Idempotency

Voice APIsWhatsApp Business API
KeyIdempotency-Key request header, 1 to 128 visible characters. A longer key is refused with HTTP 400.externalId in the body (the Idempotency-Key header is accepted too), up to 160 characters.
Window24 hours per account.The life of the campaign.
A repeatReplays the stored response. The one exception is a 5xx raised after the call was already handed to the network: that reply is stored as call_state_unknown with a sentence appended telling you to check the call before retrying. A 400 or 404 is stored for the 24 hours too, so once you fix the request or the dashboard setting, send it with a new key.HTTP 200 with duplicate: true and the earlier delivery's current status.
Replay markerIdempotent-Replayed: true, plus the original idempotency-replayed: true header.duplicate: true in the body.
Same key, different bodyHTTP 422 with idempotency_conflict.The first send stands; the second is reported as a duplicate.
Still in flightHTTP 409 with idempotency_in_progress and Retry-After.Not applicable.

Rate limits and headers

Voice APIsWhatsApp Business API
BudgetPer account: 120 reads a minute and 120 writes a minute, counted separately, so polling can never starve call placement.Per campaign token: 300 requests a minute over a sliding window.
Limit headersRateLimit-Limit, RateLimit-Remaining and RateLimit-Reset, with X-RateLimit-* aliases of the same three values.None.
How long to waitRetry-After on every 429 and every 409, mirrored in the body as retry_after_sec.Retry-After on rate_limited; details.retryAfter (IST) on quiet_hours.
Capacity refusalHTTP 429 concurrency_limit when the account has no free line, with lines, lines_in_use and retry_after_sec in the body and a Retry-After of 5 seconds. Call-placing responses also carry X-Agentive-Lines and X-Agentive-Lines-In-Use.Not applicable; there are no lines to exhaust.

Webhook signing

Voice APIsWhatsApp Business API
Header to verifyX-Agentive-Signature-V2: t=<unix seconds>,v2=<hex>X-Agentive-Signature: <hex>, with no prefix.
What is signedHMAC-SHA256, with the signing secret, of t, a dot, then the exact raw body.HMAC-SHA256 of the exact raw body with the endpoint's signing secret.
FreshnessReject a t more than 300 seconds from your own clock. The timestamp is inside the signed material, so a captured delivery cannot be sent again later.Nothing time-bound is signed. De-duplicate on the event id for good, and accept deliveries over HTTPS only.
ComparisonConstant time, on bytes. Reject on any mismatch, and reject a delivery with no version 2 header.Constant time, on bytes. Reject on any mismatch.
Two different signatures
The Voice APIs sign the timestamp together with the body, and you verify only X-Agentive-Signature-V2. Voice deliveries also carry the older body-only X-Agentive-Signature for receivers built before version 2; do not accept it on its own, because it proves nothing about when a body was sent. The WhatsApp signature is the body alone with no prefix. A shared handler needs one verifier per product.

Webhook delivery headers

Voice APIsWhatsApp Business API
Event nameX-Agentive-EventX-Agentive-Event
Event idX-Agentive-Event-Id, the same value as id in the body. Shared by every endpoint that receives the event.X-Agentive-Delivery, the same value as id in the body. Despite the name it is the event id, not a per-endpoint delivery id.
Delivery idX-Agentive-Delivery-Id (dlv_...), one per event per endpoint, stable across every retry.None. X-Agentive-Delivery is the Chat product's name for the event id above.
Attempt numberX-Agentive-Attempt, 1-based, counting through the whole retry schedule.None.
Attempt timeX-Agentive-Timestamp, Unix seconds at the moment of this attempt, the same value as t in the version 2 signature. Check the age against the signed t, never against this header alone.X-Agentive-Timestamp, the same timestamp as the envelope.
User agentAgentive-Webhooks/2026-06-01Agentive-Webhooks/2026-05-08, the Chat payload version.

Webhook retries

Voice APIsWhatsApp Business API
AttemptsNine: three fast, then six spread out.Three.
Schedule0.5 s and 2 s between the first three, then 1 min, 5 min, 30 min, 2 h, 6 h and 12 h.0 s, 2 s and 8 s.
Total windowAbout 24 hours, after which the delivery is marked failed.About 10 seconds.
Timeout per attempt6 seconds.10 seconds.
What you seeThe dashboard lists recent deliveries per endpoint with the event, the latest result, the number of tries and the time in IST.The campaign's Deliveries tab shows the message and its current status.

Timestamps and amounts

Voice APIsWhatsApp Business API
Time zoneIndian Standard Time, ISO 8601 with a +05:30 offset. The field is named per product: created_at_ist on a call, expires_at_ist on a verification, timestamp_ist on a webhook envelope.timestamp on the webhook envelope is UTC ISO 8601. Schedules and quiet hours are set and reported in IST.
UTC alongsidecreated_at_utc on a call, and occurred_at (UTC) plus created (Unix seconds) on a webhook envelope.The envelope timestamp is already UTC.
MoneyIndian Rupees, always. balance_inr is a number, never a formatted string.Indian Rupees, always. Amounts appear in the dashboard, not in the send API.

Versioning and field case

Voice APIsWhatsApp Business API
API versionIn the path: /api/public/v1.In the path: /api/v1.
Payload versionapi_version on every webhook event. Currently 2026-06-01.apiVersion on every webhook event. Currently 2026-05-08.
CompatibilityFields are added, never removed or redefined. Ignore fields you do not recognise.Fields are added, never removed or redefined. Ignore fields you do not recognise.
Field casesnake_case throughout, request and response.camelCase throughout, request and response.

Security

  • Every credential is a secret. That includes the Voice publishable key, whatever its name suggests: treat it exactly like the secret. Keep all keys on your server, in an environment variable or a secrets store, never in a browser, a mobile app, a spreadsheet or source control.
  • Send them only to the API. Never forward a key or a secret to any other host, and do not let an HTTP client carry them across a redirect to another host.
  • Rotate at once if one leaks. Rotate the Voice pair from the API Access tab of the Voice dashboard and a WhatsApp token from its campaign page. The old value stops working immediately, so update your server in the same step.
  • HTTPS only. Write https:// in the base URL in your code. A request sent over plain HTTP has already exposed its credentials before any redirect can protect it.
  • No address allow-listing today. Requests are not restricted to your server's IP addresses, and webhooks are not sent from a fixed list of addresses. Authenticate every webhook by its signature, never by where it came from.
Report a vulnerability
If you find a security problem in the APIs, the webhooks or the dashboard, write to hello@agentive.co.in with the steps to reproduce it. Please do not test against accounts that are not yours. Our contact details are also published at /.well-known/security.txt.
Reading this as one platform
The habits that hold across both products: HTTPS only, JSON both ways, a stable machine code on every error, an idempotency key on every request a retry could repeat, HMAC-SHA256 on every webhook, Indian Rupees and Indian Standard Time. The habits that do not: the credential header, the envelope key names, the field case, the signature scheme and the retry schedule. Write one transport layer per product, then share everything above it.

Changelog

Changes that could affect code you have already written. Everything not listed here is additive: new fields, new headers and new optional request fields, which a handler that ignores what it does not recognise absorbs on its own.

September 2026

What changedIt used toIt nowWhat to do
Webhook verification is version 2 only (29 Sep)The samples verified X-Agentive-Signature-V2 when present and fell back to the body-only X-Agentive-Signature when it was absent.Every sample verifies X-Agentive-Signature-V2 only, rejects a timestamp older than five minutes, and refuses a delivery that does not carry it. Every delivery carries it.Remove any fallback to X-Agentive-Signature from your receiver. A body-only signature can be replayed by anyone who captured one delivery, so accepting it keeps that door open.
Recordings are streamed (29 Sep)GET /calls/:unique_id/recording usually answered 302 with a short-lived download link, and the samples told your client to follow it.The API answers 200 with the audio itself (206 for a Range request) and never redirects. The samples authenticate with HTTP Basic.Nothing breaks: a client that followed the redirect reads the audio directly now. Stop sending your secret to any host other than the API; custom headers such as x-api-secret are carried across a redirect by most HTTP clients.
AI voice agent API documented (29 Sep)POST /ai/calls worked but was undocumented, and an AI voice agent API campaign could not be triggered.A full AI Voice Agent API reference. The trigger runs AI campaigns and takes variables and metadata, and AI calls fire call.analysed.Invalid variables are now refused with 400 validation_error naming the key, instead of being dropped. Check the rules before you send them.
A wrong secret is a 401A known publishable key sent with a wrong secret returned 403.Returns 401, with the same "Invalid API credentials." sentence, so the status can no longer tell an attacker that a key exists.Move any branch that read 403 as a bad secret to 401. On the Voice APIs, 401 now always means the credentials were rejected and 403 always means they were accepted without entitlement.
Webhook status matches the eventdata.status could disagree with the event name: a call that rang unanswered or was busy sometimes arrived as failed, and a call that could not be placed sometimes arrived as missed.data.status is derived from the event name, so call.no_answer and call.busy are always missed and call.failed is always failed.Nothing, if you branch on the event type or on end_reason. Remove any workaround that corrected the old values.
Webhook User-AgentAn internal build string that did not match the Agentive-Webhooks/... form the docs promised.Agentive-Webhooks/2026-06-01, the payload version, so it changes only when api_version does.Update any allow-list or log filter that matched the old string. Never authenticate a delivery on the User-Agent; verify the signature.
unique_id on a direct AI callEvents after call.initiated for a call placed straight to an AI agent carried an internal session id in data.unique_id, not the id the placing response returned.data.unique_id is the id you were given when you placed the call, on every event, and unique_id is the same on every read of the call.Nothing for broadcast, Interactive Voice or verification calls; their ids are unchanged. For direct AI calls, match on the id the placing response returned, which now works throughout.
Also on 29 September
A request's Idempotency-Key longer than 128 characters is refused with HTTP 400 instead of being cut short. The per-address limit before authentication now counts only requests refused with 401 or 403, and failed secrets are counted per publishable key and client address, so a correct secret is always let through. Every webhook address must use https:// on port 443 or 8443, checked on every delivery, so an address saved earlier on plain http:// or another port needs changing. A custom signing secret must be at least 32 characters, and an account can register up to 10 endpoints. An account with the AI voice agent and not voice broadcast reads and receives webhooks for its AI calls only; any other account, including one with neither product, reads and receives all its calls. The number_flood and daily_cap refusals carry Retry-After and retry_after_sec.
Also new, and safe to ignore until you want it
A string error_code beside the numeric code on every Voice error, an error key carrying the same sentence as details, Retry-After on every 429 and 409, X-RateLimit-* aliases, X-Agentive-Delivery-Id and X-Agentive-Attempt on webhook deliveries, a webhook retry tail that keeps trying for about 24 hours, created_at_ist and created_at_utc on the call object, and verification_status on verifications.

Need help?

Stuck on an integration, or need something the API does not cover yet? Write to the team and an engineer will reply.

Contact us