This page documents the Click2Call API flow to authenticate, create async click2call jobs, receive callback events, list recent call logs, and fetch transcript status using internal call IDs.
https://developer.induslabs.ioClick2Call API route prefix: /api.
{
"status_code": 200,
"message": "string or null",
"error": "string/object or null",
"data": {}
}
Auth/dependency failures may return FastAPI default errors like:
{ "detail": "Could not validate credentials" }
/api/loginAuthenticate a verified active user and return access + refresh tokens.
| Name | Type | Default | Description |
|---|---|---|---|
email* | string | required | User email address. |
password* | string | required | User password. |
| Status | Type | Description |
|---|---|---|
200 OK | application/json | Login successful with access and refresh tokens. |
400 Bad Request | application/json | Incorrect credentials, inactive user, or unverified user. |
curl -X POST \
"https://developer.induslabs.io/api/login" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "your_password"
}'
{
"status_code": 200,
"message": "Login successful",
"error": null,
"data": {
"access_token": "<jwt_access_token>",
"refresh_token": "<jwt_refresh_token>",
"token_type": "bearer"
}
}
/api/calls/click2callCreate a click2call job for authenticated user. Call is queued and processed asynchronously.
| Name | Type | Default | Description |
|---|---|---|---|
Authorization* | header | required | Bearer <access_token> |
customer_number* | string | required | Customer phone number, e.g. 919999999999. |
agent_number* | string | required | Agent phone number, e.g. 918888888888. |
did | string | required for provider flow | Caller DID/provider number used to place the Click2Call request. |
callback_url | url | optional | Public webhook URL that receives backend POST callbacks for this call. |
transcript | boolean | false | Set true to process recording transcript after the provider call-log callback arrives. |
transcript_language | string | null | Optional transcript language. If omitted, the default hi-en transcription flow is used. |
agent_config | object | {} | Optional config for AGT_ voice-agent calls. Ignored for normal provider phone-number flow. |
| Status | Type | Description |
|---|---|---|
200 OK | application/json | Click2Call request created and queued. |
401 Unauthorized | application/json | Missing or invalid token. |
422 Unprocessable Entity | application/json | did is missing for provider flow, callback_url is invalid, or request validation failed. |
400 Bad Request | application/json | Inactive user or validation issues. |
curl -X POST \
"https://developer.induslabs.io/api/calls/click2call" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-d '{
"customer_number": "919999999999",
"agent_number": "918888888888",
"did": "919484956750",
"callback_url": "https://example.com/webhooks/indus/click2call",
"transcript": true,
"transcript_language": "hi"
}'
{
"status_code": 200,
"message": "Click2Call request created",
"error": null,
"data": {
"call_id": "call_ab12cd34ef56gh78",
"status": "queued",
"did": "919484956750",
"callback_url": "https://example.com/webhooks/indus/click2call",
"transcript": true,
"transcript_language": "hi"
}
}
/api/calls/recentFetch paginated Click2Call records for the authenticated user with filters for call status, transcript status, phone numbers, DID, and date range.
| Name | Type | Default | Description |
|---|---|---|---|
Authorization* | header | required | Bearer <access_token> |
status | query string | optional | Exact call status filter, e.g. queued, completed, failed, Answered. |
call_type | query string | optional | Exact call type filter, e.g. C2C, outbound, agent_telephony. |
transcript_status | query string | optional | Filter by pending, processing, ready, disabled, or failed. |
customer_number | query string | optional | Case-insensitive partial match on customer number. |
agent_number | query string | optional | Case-insensitive partial match on agent number or AGT_ id. |
did | query string | optional | Case-insensitive partial match on DID. |
date_from | ISO datetime | optional | Return records created at or after this date. Z timezone is accepted. |
date_to | ISO datetime | optional | Return records created at or before this date. Z timezone is accepted. |
limit | integer | 20 | Page size. Must be between 1 and 200. |
page | integer | 1 | Page number. Must be 1 or higher. |
| Status | Type | Description |
|---|---|---|
200 OK | application/json | Paginated recent Click2Call records. |
401 Unauthorized | application/json | Missing or invalid token. |
422 Unprocessable Entity | application/json | Invalid pagination or date filter. |
curl -X GET \
"https://developer.induslabs.io/api/calls/recent?limit=10&page=1&transcript_status=ready" \
-H "Authorization: Bearer <access_token>"
{
"status_code": 200,
"message": "Recent call logs fetched",
"error": null,
"data": {
"total": 1,
"page": 1,
"limit": 10,
"has_more": false,
"filters": {
"status": null,
"call_type": null,
"transcript_status": "ready",
"customer_number": null,
"agent_number": null,
"did": null,
"date_from": null,
"date_to": null
},
"calls": [
{
"call_id": "call_ab12cd34ef56gh78",
"status": "completed",
"customer_number": "919999999999",
"agent_number": "918888888888",
"did": "919484956750",
"duration": "52",
"answer_duration": "48",
"call_type": "C2C",
"transcript_enabled": true,
"transcript_status": "ready",
"recording": "https://signed-recording-url",
"recording_url": "https://signed-recording-url",
"transcript": {
"summary": "Call summary text",
"call_outcome": "Interested",
"history": []
},
"created_at": "2026-04-14T06:50:00Z",
"updated_at": "2026-04-14T06:52:00Z"
}
]
}
}
/api/calls/{call_id}/transcriptFetch transcript metadata/content for a previously created click2call request.
| Name | Type | Default | Description |
|---|---|---|---|
Authorization* | header | required | Bearer <access_token> |
call_id* | path | required | Call ID returned by click2call endpoint. |
| Status | Type | Description |
|---|---|---|
200 OK | application/json | Transcript pending, ready, disabled, or failed payload. |
403 Forbidden | application/json | User is not authorized for this call. |
404 Not Found | application/json | call_id not found. |
401 Unauthorized | application/json | Missing or invalid token. |
curl -X GET \
"https://developer.induslabs.io/api/calls/call_ab12cd34ef56gh78/transcript" \
-H "Authorization: Bearer <access_token>"
{
"status_code": 200,
"message": "Transcript not available yet",
"error": null,
"data": {
"call_id": "call_ab12cd34ef56gh78",
"transcript_status": "pending",
"customer_number": "xxxxx9999999",
"agent_number": "xxxxx8888888",
"duration": null,
"recording": "pending",
"transcript": null
}
}
{
"status_code": 200,
"message": "Transcript found",
"error": null,
"data": {
"call_id": "call_ab12cd34ef56gh78",
"transcript_status": "ready",
"customer_number": "xxxxx9999999",
"agent_number": "xxxxx8888888",
"duration": "52",
"recording": "https://signed-recording-url",
"transcript": {
"transcript_id": "67c7....",
"summary": "Call summary text",
"call_outcome": "Interested",
"history": [],
"createdAt": "2026-03-05T10:00:00Z",
"updatedAt": "2026-03-05T10:01:00Z"
}
}
}
{
"status_code": 200,
"message": "Transcript processing failed",
"error": null,
"data": {
"call_id": "call_ab12cd34ef56gh78",
"transcript_status": "failed",
"customer_number": "xxxxx9999999",
"agent_number": "xxxxx8888888",
"duration": "52",
"recording": "https://signed-recording-url",
"transcript": null,
"error": "Client error '401 Unauthorized' for url 'https://voice.induslabs.io/v1/audio/transcribe/diarize'"
}
}
callback_url is your webhook endpoint. When you pass it in the create request, the backend sends POST requests to that URL as the call moves through completion and transcript states.
POST /api/calls/click2call with callback_url.call_id immediately. Store it.transcript is true.callback_url.callback_url must be publicly reachable from the backend. Do not use localhost for production calls.data object uses the same compact shape as GET /api/calls/{call_id}/transcript.callback_url is supplied, no webhook is sent. Use GET /api/calls/recent or transcript polling.| Event | Meaning |
|---|---|
call.completed | The call has reached a completed terminal state and call-log data was stored. |
call.failed | The call failed to connect or the provider reported a failed terminal state. |
transcript.ready | Recording transcript processing completed successfully. |
transcript.failed | Transcript processing failed. The failure reason is sent in top-level error and data.error. |
transcript.disabled | transcript was false, so transcript processing was skipped. |
{
"status_code": 200,
"message": "Call completed",
"error": null,
"event": "call.completed",
"data": {
"call_id": "call_ab12cd34ef56gh78",
"transcript_status": "processing",
"customer_number": "xxxxx9999999",
"agent_number": "xxxxx8888888",
"duration": "52",
"recording": "https://signed-recording-url",
"transcript": null
}
}
{
"status_code": 200,
"message": "Transcript ready",
"error": null,
"event": "transcript.ready",
"data": {
"call_id": "call_ab12cd34ef56gh78",
"transcript_status": "ready",
"customer_number": "xxxxx9999999",
"agent_number": "xxxxx8888888",
"duration": "52",
"recording": "https://signed-recording-url",
"transcript": {
"transcript_id": "67c7....",
"summary": "Call summary text",
"call_outcome": "Interested",
"history": [],
"createdAt": "2026-03-05T10:00:00Z",
"updatedAt": "2026-03-05T10:01:00Z"
}
}
}
{
"status_code": 500,
"message": "Transcript processing failed",
"error": "Client error '401 Unauthorized' for url 'https://voice.induslabs.io/v1/audio/transcribe/diarize'",
"event": "transcript.failed",
"data": {
"call_id": "call_ab12cd34ef56gh78",
"transcript_status": "failed",
"customer_number": "xxxxx9999999",
"agent_number": "xxxxx8888888",
"duration": "52",
"recording": "https://signed-recording-url",
"transcript": null,
"error": "Client error '401 Unauthorized' for url 'https://voice.induslabs.io/v1/audio/transcribe/diarize'"
}
}
access_token.did, optional callback_url, and transcript: true when transcript is needed.call_id from the create response.callback_url is configured.GET /api/calls/recent to list and filter many calls efficiently.GET /api/calls/{call_id}/transcript when you need a single call transcript payload.BASE_URL="https://developer.induslabs.io"
LOGIN_RESP=$(curl -s -X POST "$BASE_URL/api/login" \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"your_password"}')
ACCESS_TOKEN=$(echo "$LOGIN_RESP" | jq -r '.data.access_token')
CALL_RESP=$(curl -s -X POST "$BASE_URL/api/calls/click2call" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"customer_number":"919999999999",
"agent_number":"918888888888",
"did":"919484956750",
"callback_url":"https://example.com/webhooks/indus/click2call",
"transcript":true,
"transcript_language":"hi"
}')
CALL_ID=$(echo "$CALL_RESP" | jq -r '.data.call_id')
curl -s -X GET "$BASE_URL/api/calls/recent?limit=10&page=1" \
-H "Authorization: Bearer $ACCESS_TOKEN"
curl -s -X GET "$BASE_URL/api/calls/$CALL_ID/transcript" \
-H "Authorization: Bearer $ACCESS_TOKEN"
transcript: null while processing; this is expected.transcript_status: failed and the detailed reason in data.error.did.