Agentive
Agentive
Cloud TelephonyAI Voice AgentAI Chat AgentAboutContact
80056 80053
Book a Demo
Agentive
Agentive

One platform for every Indian business. Cloud telephony, an AI voice agent, an AI chat agent and the WhatsApp Business API, all in one place. Answer every call and message, and go live in a day.

Follow Us

Product

  • Cloud Telephony
  • AI Voice Agent
  • AI Chat Agent

Company

  • About Us
  • Contact Us
  • Disclaimer

Legal

  • Privacy Policy
  • Data Deletion
  • Terms of Service
  • Refund Policy
  • Shipping Policy
Meta Business PartnerAvailable on Google PlayAvailable on the App Store

© 2026 Agentive. Owned and operated by Mannan Technologies Private Limited.

HomeDevelopersAPI Reference
API ReferenceWebhooks

On this page

Introduction
Base URL
Authentication
Response format
Error codes
Rate limits
Endpoints
Place a callTrigger a campaignSend a code (OTP)Verify a codeGet call statusList callsDownload a recordingList campaignsGet account balance
The call object
Status and end reasons
Phone number format
Reference IDs
Idempotency
Quick start

API Reference

Voice API Reference

Place voice calls, run verification (OTP) calls, trigger saved campaigns, and check call status directly from your own systems over a simple JSON REST API.

Base URL
https://voice.agentive.co.in/api/public/v1
Format
JSON over HTTPS
Currency / time
INR / IST

Introduction

The Agentive Voice API gives your application programmatic access to the same calling stack that powers the dashboard. Place a single outbound call, read a verification code out to a customer, run a saved campaign for one number, or poll the result of any call you started.

Every amount is in Indian Rupees (INR). Every timestamp is in Indian Standard Time (IST), in ISO 8601 format. Every request is authenticated with a publishable key and a secret, and every response uses one consistent JSON envelope so your integration code stays simple.

Two products, one reference
This page covers placing calls and checking status. To receive call and verification events in real time instead of polling, see the Webhooks reference.

Base URL

Every endpoint path below is relative to this base URL.

Base URL
https://voice.agentive.co.in/api/public/v1

Authentication

Every request must be authenticated with two credentials issued to your account.

CredentialWhat it isHow to send it
Publishable keyYour account's public lookup handle. Starts with pk_live_.x-api-key request header
Secret keyYour account's private proof. Starts with sk_live_. Treat it like a password.x-api-secret request header (preferred), or a secret field in the JSON body

View and rotate both keys from the API tab in your dashboard. The secret is shown in full only once, when it is first generated or rotated; afterwards it is masked. If you lose it, rotate to generate a new pair, and the old secret stops working immediately.

The header form is recommended because it keeps the secret out of request bodies and most log formats. If you send the secret in both the header and the body, the header value is used. There is a single set of live credentials per account; both keys begin with a _live_ prefix and every call is processed against your live account.

HTTP Basic authentication

As an alternative to the two headers, you may send the credentials with HTTP Basic auth, using the publishable key as the username and the secret as the password. This is the familiar curl -u form. When an x-api-key header is present it takes precedence; otherwise the Basic credentials are used.

cURL
curl https://voice.agentive.co.in/api/public/v1/account \
  -u pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keep the secret server-side
Never embed the secret key in a browser, mobile app, or any client a customer can inspect. All requests must be over HTTPS. If a key is exposed, rotate it from the dashboard at once.

Example: authenticated request

cURL
curl https://voice.agentive.co.in/api/public/v1/calls \
  -H "x-api-key: pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "x-api-secret: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "type": "audio_blast", "number": "9812345678", "audio_id": 12 }'

Authentication failures

SituationHTTPdetails message
No publishable key sent401Missing API key. Send your publishable key in the x-api-key header.
Unknown publishable key401Invalid API credentials.
Known key, wrong or missing secret403Invalid API credentials.
Account is not active403This account is not active. Please contact support.
API access not enabled for the account403The API is not enabled for this account. Please contact support.

The wording is intentionally the same for an unknown key and a wrong secret, so that credentials cannot be probed.

Response format

Every response is JSON and uses one consistent envelope.

JSON
{
  "status": "success",
  "code": 200,
  "unique_id": "run_4821",
  "reference_id": "order-99213",
  "details": "Call queued."
}
FieldTypeDescription
statusstring"success" or "error".
codenumberA numeric result code. Mirrors the HTTP status (see Error codes).
unique_idstring | nullOur identifier for the resource created by this call. Use it with Get call status. For OTP requests this is the verification request id.
reference_idstring | nullEchoes the reference_id you sent, so you can correlate the response with your own records. null if you did not send one.
detailsstringA short human-readable description of the result.

Successful responses may include extra fields alongside the envelope. These are documented per endpoint (for example request_id and expires_in_sec on OTP send, verified on verify, call_status on status).

HTTP status
A successful request returns HTTP 200 with status: "success". A failed request returns the matching HTTP error status (400, 401, 403, 404, 429, or 5xx) with status: "error", and the same value in the code field.

Error codes

HTTPcodeMeaningWhen it happens
200200SuccessThe request was accepted.
400400Bad requestA required field is missing or invalid (a malformed number, an unknown type, a missing audio_id, or a missing code on verify).
401401UnauthorizedThe publishable key is missing or unknown, or (on verify) the submitted code is incorrect.
403403ForbiddenThe secret is wrong, the account is not active, or API access is not enabled.
404404Not foundThe campaign id, call id, or verification request could not be found for your account.
429429Too many requestsYou exceeded the rate limit, or sent too many verification calls to one number in a short window.
5xx5xxTemporary problemThe call could not be placed right now. Safe to retry after a short pause.

Error responses never include internal infrastructure detail. A failed call placement returns a neutral message such as "Could not place the call right now. Please retry."

Example error response

JSON
{
  "status": "error",
  "code": 400,
  "unique_id": null,
  "reference_id": "order-99213",
  "details": "A valid Indian mobile number is required."
}

Rate limits

Requests are limited per account to 120 requests per minute. The limit is keyed to your account, so traffic from one account never throttles another, and an office behind a single shared IP is not treated as one caller.

When you exceed the limit you receive HTTP 429 with:

JSON
{
  "status": "error",
  "code": 429,
  "details": "Too many requests. Please slow down and retry shortly."
}

Standard rate-limit headers (RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset) are returned on responses so you can pace your requests.

Verification calls have a tighter cap
Verification (OTP) calls are capped at 3 per number per 10 minutes. Exceeding that returns HTTP 429 with a message about too many verification calls to that number.

Endpoints

The write endpoints place a call, trigger a saved campaign, send a voice verification code, and verify a code. The read endpoints fetch a single call's status, list your calls, download a recording, list your campaigns, and report your account balance.

Place a call

POST/calls

Place a single outbound call immediately. Three call types are supported.

typeWhat it doesRequired fields
audio_blastPlays a pre-recorded audio clip from your library to the number, then ends.audio_id
press1Plays a clip and listens for a keypad press to connect the call onward.audio_id
otpPlaces a verification call that reads out a code.none beyond number

Request fields

FieldTypeRequiredDescription
typestringRequiredOne of audio_blast, press1, otp.
numberstringRequiredThe recipient's Indian mobile number. See Phone number format.
audio_idnumberOptionalFor audio_blast and press1. The id of a clip in your audio library. Must belong to your account.
dtmf_mapobjectOptionalpress1 only. Maps a pressed digit to an action. Defaults to { "1": "connect_agent" }.
caller_idstringOptionalA verified caller number on your account to display. Defaults to your account default.
codestringOptionalotp only. Supply your own numeric code. If omitted, a code is generated.
lengthnumberOptionalotp only. Length of the generated code, 4 to 8 digits. Default 4.
ttlnumberOptionalotp only. Seconds the code stays valid. Default 600 (10 minutes).
messagestringOptionalotp only. A custom spoken message. Use {code} where the code should be read out.
reference_idstringOptionalYour own correlation key. Echoed back and in webhooks.

Response (audio_blast / press1)

JSON
{
  "status": "success",
  "code": 200,
  "unique_id": "run_4821",
  "reference_id": "order-99213",
  "details": "Call queued."
}

For the otp type the response is the same as Send a verification code.

Examples

curl https://voice.agentive.co.in/api/public/v1/calls \
  -H "x-api-key: pk_live_..." \
  -H "x-api-secret: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "audio_blast",
    "number": "9812345678",
    "audio_id": 12,
    "reference_id": "order-99213"
  }'

Press-1 example body

JSON
{
  "type": "press1",
  "number": "9812345678",
  "audio_id": 18,
  "dtmf_map": { "1": "connect_agent" },
  "reference_id": "promo-march"
}

Trigger a saved campaign

POST/campaigns/:id/trigger

Run an existing API campaign for a single number. The campaign's audio and settings are used as configured in your dashboard. Only Audio Blast and Press-1 campaigns can be triggered this way. Verification-code campaigns use the OTP endpoints instead.

Path parameter

ParameterDescription
idThe numeric id of the campaign to trigger.

Request fields

FieldTypeRequiredDescription
numberstringRequiredThe recipient's Indian mobile number.
reference_idstringOptionalYour own correlation key.

Response

JSON
{
  "status": "success",
  "code": 200,
  "unique_id": "run_4822",
  "reference_id": "lead-5567",
  "details": "Call queued."
}

Error cases

SituationHTTPdetails
Campaign not found for your account404Campaign not found.
Campaign is a verification-code campaign400This is a verification-code campaign. Use the OTP endpoints to send a code.
Campaign type cannot be triggered for one number400This campaign type cannot be triggered for a single number.
Campaign has no audio configured400This campaign has no audio configured.

Examples

curl https://voice.agentive.co.in/api/public/v1/campaigns/57/trigger \
  -H "x-api-key: pk_live_..." \
  -H "x-api-secret: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "number": "9812345678", "reference_id": "lead-5567" }'

Send a verification code (voice OTP)

POST/otp/send

Place a call that reads a numeric verification code out to the recipient. The code is read digit by digit and spoken twice, then the call ends. There is no agent and no human on the call.

The code is never returned
The code is generated for you (or you may supply your own). It is stored hashed; the plain code is never returned in any response and never written to any log. To check what the recipient entered, use Verify a code.

Request fields

FieldTypeRequiredDescription
numberstringRequiredThe recipient's Indian mobile number.
codestringOptionalSupply your own numeric code (4 to 8 digits). If omitted, one is generated.
lengthnumberOptionalLength of the generated code, 4 to 8. Default 4.
ttlnumberOptionalSeconds the code stays valid. Default 600 (10 minutes).
max_attemptsnumberOptionalHow many verify attempts are allowed. Default 3.
messagestringOptionalCustom spoken message. Use the token {code} where the digits should be read. If omitted, a default sentence is used.
reference_idstringOptionalYour own correlation key.

Response

JSON
{
  "status": "success",
  "code": 200,
  "unique_id": "5f3c8b2a-1d4e-4a9c-9e7b-2c6f0a1b3d8e",
  "reference_id": "signup-7781",
  "details": "Verification call queued.",
  "request_id": "5f3c8b2a-1d4e-4a9c-9e7b-2c6f0a1b3d8e",
  "expires_in_sec": 600
}
Extra fieldDescription
request_idThe verification request id. Use it (or the number) when calling verify. Same value as unique_id.
expires_in_secSeconds until the code expires.

Defaults: code length 4, validity 10 minutes, 3 attempts.

Spoken message: by default the call says "Your verification code is 1 2 3 4. Again, 1 2 3 4." If you pass a message with a {code} token, your text is read with the spaced digits substituted in.

Examples

curl https://voice.agentive.co.in/api/public/v1/otp/send \
  -H "x-api-key: pk_live_..." \
  -H "x-api-secret: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "number": "9812345678", "length": 4, "ttl": 600, "reference_id": "signup-7781" }'

Verify a code

POST/otp/verify

Check a code the recipient gives you against a verification request. Identify the request by its request_id (returned from send) or by the recipient's number (the most recent pending request for that number is used).

Each verify attempt is counted whether right or wrong. Once the attempt cap is reached the request can no longer be verified, and you must send a fresh code.

Request fields

FieldTypeRequiredDescription
codestringRequiredThe code the recipient entered.
request_idstringOptionalOne of request_id or number. The id returned by send.
numberstringOptionalOne of request_id or number. The recipient's number, used to find the most recent pending request.
reference_idstringOptionalYour own correlation key.

Response (correct code)

JSON
{
  "status": "success",
  "code": 200,
  "unique_id": "5f3c8b2a-1d4e-4a9c-9e7b-2c6f0a1b3d8e",
  "reference_id": "signup-7781",
  "details": "Code verified.",
  "request_id": "5f3c8b2a-1d4e-4a9c-9e7b-2c6f0a1b3d8e",
  "verified": true
}

Response (incorrect code)

JSON
{
  "status": "error",
  "code": 401,
  "details": "Incorrect code.",
  "verified": false,
  "attempts_left": 2
}
SituationHTTPdetails
Code is correct200Code verified.
Code is incorrect401Incorrect code.
Code has expired400This code has expired.
Too many incorrect attempts400Too many incorrect attempts.
Code already used400This code has already been used.
Request not found400Verification failed.
Missing code or identifier400A code and either request_id or number are required.

The verified field is always present (true or false). On a wrong code, attempts_left tells you how many tries remain.

Examples

curl https://voice.agentive.co.in/api/public/v1/otp/verify \
  -H "x-api-key: pk_live_..." \
  -H "x-api-secret: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "request_id": "5f3c8b2a-1d4e-4a9c-9e7b-2c6f0a1b3d8e", "code": "1234" }'

Get call status

GET/calls/:unique_id

Check the current status of a call you placed, or a verification request.

Path parameter

ParameterDescription
unique_idThe unique_id returned when you placed the call or sent the code. For calls this looks like run_4821; for verification it is the request id.

Response (a placed call)

JSON
{
  "status": "success",
  "code": 200,
  "unique_id": "run_4821",
  "reference_id": null,
  "details": "answered",
  "call_status": "answered",
  "duration_sec": 17
}

Response (a verification request)

JSON
{
  "status": "success",
  "code": 200,
  "unique_id": "5f3c8b2a-1d4e-4a9c-9e7b-2c6f0a1b3d8e",
  "reference_id": "signup-7781",
  "details": "verified",
  "call_status": "verified",
  "verified": true,
  "attempts": 1,
  "max_attempts": 3
}

Call status values

ValueMeaning
queuedAccepted and waiting to be placed.
ringingThe recipient's phone is ringing.
answeredThe recipient answered and the call is in progress.
completedThe call finished after being answered.
failedThe call ended without connecting.

Verification status values

ValueMeaning
pendingCode sent, not yet verified or expired.
verifiedThe correct code was confirmed.
expiredThe validity window passed.
failedThe attempt cap was reached, or the call could not be placed.

A unique_id that does not belong to your account returns HTTP 404 with "Call not found." or "Not found.".

Listing calls in bulk
This endpoint reports a single call or verification request you started. To page through your call history (including inbound calls), use List calls, which returns the richer call object with the enumerated status and end_reason values.

Examples

curl https://voice.agentive.co.in/api/public/v1/calls/run_4821 \
  -H "x-api-key: pk_live_..." \
  -H "x-api-secret: sk_live_..."

List calls

GET/calls

Page through the calls on your account, most recent first. This returns the full call object for each call, with the enumerated status and end_reason values, so you can reconcile call results in bulk instead of polling each call by id.

Query parameters

ParameterTypeDefaultDescription
pagenumber1The page of results to return.
per_pagenumber50Results per page. Maximum 100.
directionstringnoneFilter by inbound or outbound.
statusstringnoneFilter by a call status: queued, ringing, in_progress, completed, failed, or missed.
fromstringnoneInclude calls created on or after this ISO 8601 date or timestamp.
tostringnoneInclude calls created before this ISO 8601 date or timestamp.
numberstringnoneMatch calls where this number appears as either the caller or the recipient.

Response

JSON
{
  "status": "success",
  "code": 200,
  "data": [
    {
      "unique_id": "run_4821",
      "call_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
      "direction": "outbound",
      "from_number": "07965318581",
      "to_number": "+919812345678",
      "status": "completed",
      "end_reason": "completed",
      "duration_sec": 42,
      "campaign_id": 4821,
      "reference_id": "order-99213",
      "created_at": "2026-06-04T21:42:08+05:30"
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 50,
    "total": 137,
    "total_pages": 3
  }
}
FieldTypeDescription
dataarrayA page of call objects.
pagination.pagenumberThe current page.
pagination.per_pagenumberResults per page for this response.
pagination.totalnumberTotal calls matching your filters.
pagination.total_pagesnumberTotal number of pages.

The response carries only the public call object fields. end_reason is always one of the enumerated end reasons.

Examples

curl "https://voice.agentive.co.in/api/public/v1/calls?per_page=50&direction=outbound&status=completed" \
  -H "x-api-key: pk_live_..." \
  -H "x-api-secret: sk_live_..."

Download a call recording

GET/calls/:unique_id/recording

Download the audio recording of a call. The response streams the audio file and supports HTTP Range requests, so you can fetch a portion or resume a download.

Path parameter

ParameterDescription
unique_idThe call's unique_id (for example run_4821) or its call_id. Must belong to your account.

Response

On success the body is the raw audio. The Content-Type is audio/ogg or audio/wav depending on how the recording was stored. With a Range request the response is HTTP 206 (Partial Content); otherwise it is HTTP 200.

If there is no recording for the call (it never connected, or the audio is not available), the response is HTTP 404 with the standard error envelope:

JSON
{
  "status": "error",
  "code": 404,
  "details": "No recording is available for this call."
}
Get notified when it is ready
A recording is typically ready a short time after the call ends. To be notified the moment it is ready, subscribe to the recording.available webhook, which carries the same download URL.

Examples

curl "https://voice.agentive.co.in/api/public/v1/calls/run_4821/recording" \
  -H "x-api-key: pk_live_..." \
  -H "x-api-secret: sk_live_..." \
  --output call-4821.ogg

List campaigns

GET/campaigns

List the campaigns on your account that can be triggered through the API. Use a campaign id from this list with Trigger a saved campaign.

Response

JSON
{
  "status": "success",
  "code": 200,
  "data": [
    { "id": 57, "name": "March promo", "type": "audio_blast", "status": "active" },
    { "id": 61, "name": "Renewal press-1", "type": "press1", "status": "active" },
    { "id": 72, "name": "Signup verification", "type": "otp", "status": "active" }
  ]
}
FieldTypeDescription
idnumberThe campaign id. Use it with Trigger a saved campaign.
namestringThe name you gave the campaign.
typestringOne of audio_blast, press1, or otp. Verification (otp) campaigns are configured here but delivered with the OTP endpoints.
statusstringThe campaign's current state.

Examples

curl https://voice.agentive.co.in/api/public/v1/campaigns \
  -H "x-api-key: pk_live_..." \
  -H "x-api-secret: sk_live_..."

Get account balance

GET/account

Return your account's current wallet balance in INR.

Response

JSON
{
  "status": "success",
  "code": 200,
  "data": {
    "balance_inr": 1842.5,
    "currency": "INR"
  }
}
FieldTypeDescription
balance_inrnumberYour current wallet balance, in Indian Rupees.
currencystringAlways "INR".

Examples

curl https://voice.agentive.co.in/api/public/v1/account \
  -H "x-api-key: pk_live_..." \
  -H "x-api-secret: sk_live_..."

The call object

List calls returns a data array of call objects. The same shape appears in the call.* webhook events.

FieldTypeDescription
unique_idstringThe call's public id. For calls placed through an API run this looks like run_4821; otherwise it is the call id.
call_idstring | nullOur internal identifier for the call.
directionstringoutbound or inbound.
from_numberstring | nullThe caller number shown.
to_numberstring | nullThe recipient number.
statusstring | nullThe call state. One of the enumerated status values.
end_reasonstring | nullWhy the call ended. One of the enumerated end reasons, or null while the call is still in progress.
duration_secnumber | nullTalk duration in seconds.
campaign_idnumber | nullThe run this call belongs to, matching the digits in unique_id.
reference_idstring | nullThe reference_id you supplied.
created_atstring | nullWhen the call was created, in IST.

Call status and end reasons

status and end_reason are closed sets. New values are not added without notice, so you can write exhaustive handling.

status (current call state)

ValueMeaning
queuedAccepted and waiting to be placed.
ringingThe recipient's phone is ringing.
in_progressThe recipient answered and the call is connected.
completedThe call finished after being answered.
missedThe call rang but was never answered.
failedThe call ended without connecting.

end_reason (set on a final state)

ValueMeaning
completedThe call connected and finished normally.
no_answerThe call rang but the recipient never picked up. Safe to retry later.
busyThe recipient was on another call. The number is reachable, so a retry can succeed.
rejectedThe recipient actively declined the call.
canceledThe call was cancelled before it connected.
failedThe call could not be placed, for example an invalid number or a carrier problem.
Get call status reports a simpler set
Get call status reports a simpler set for a single call or verification request (queued, ringing, answered, completed, failed for calls). The enumerated status and end_reason above apply to the call object returned by List calls and sent in webhooks.

Phone number format

Send Indian mobile numbers in any of these forms; they are all normalised:

  • 10-digit local: 9812345678
  • With country code: 919812345678
  • With plus prefix: +919812345678
Mobile numbers only
The mobile number must begin with 6, 7, 8, or 9. Landline and clearly invalid numbers are rejected with HTTP 400 and "A valid Indian mobile number is required."

Reference IDs

reference_id is an optional string you attach to any request, such as an order number, ticket id, or signup id. It is:

  • echoed back in the response reference_id field, and
  • included in every webhook for the call or verification.

Use it to match our events back to your own records without storing our ids. Reference IDs are capped at 120 characters; control characters are stripped.

Idempotency

The call-placing endpoints (POST /calls and POST /otp/send) do not yet accept an idempotency key. If a request times out or the connection drops, the call may already have been placed, so a blind retry can result in a second call to the same number.

To make a retry safe:

  • Send a unique reference_id on each request and record it on your side.
  • Before retrying, check Get call status or List calls for that reference_id to see whether the call was already placed.
  • For verification, remember that each /otp/send issues a fresh code; reuse the existing request_id rather than sending again if a code is already in flight.
Webhook events are de-dupable
Each webhook event carries a stable id (evt_...) you can use to ignore repeats. See Ordering and idempotency in the webhook reference.

Quick start

  1. 1
    Open the API tab in your dashboard and copy your publishable key and secret. Reveal the secret once and store it securely.
  2. 2
    Pick or upload an audio clip in your audio library and note its id.
  3. 3
    Place a test call:
    cURL
    curl https://voice.agentive.co.in/api/public/v1/calls \
      -H "x-api-key: pk_live_..." \
      -H "x-api-secret: sk_live_..." \
      -H "Content-Type: application/json" \
      -d '{ "type": "audio_blast", "number": "98XXXXXXXX", "audio_id": 12, "reference_id": "test-1" }'
  4. 4
    Note the unique_id and poll status:
    cURL
    curl https://voice.agentive.co.in/api/public/v1/calls/run_XXXX \
      -H "x-api-key: pk_live_..." \
      -H "x-api-secret: sk_live_..."
  5. 5
    To receive call results automatically instead of polling, set up a webhook.
Billing
All calls are billed in INR against your account balance, at your account's per-minute rate, subject to your account's calling limits. Timestamps in responses and webhooks are in IST.