Mon-Fri 10am - 6pm
Place a Click to Call
Base URL for your account: https://cpaas.studio
GET
POST
/api/voice/v1/click2call
Places one Click to Call from one of your account's DIDs. Requires a key scoped to voice.click2call or all. A 202 means the call was accepted — it is billed later, after the CDR, and only if it connects. Only one Click to Call may be in flight per account.
Parameters
| Param | Type | Required | Notes |
|---|---|---|---|
did_id |
integer | yes | A Click to Call-eligible active DID belonging to your account. |
agent_number |
string | yes | The agent leg. 10 digits, 0 + 10 digits, or country code + 10 digits — all normalized. |
customer_number |
string | yes | The customer leg. Same normalization. Must differ from agent_number. |
reference |
string, max 64 | no | Your own label, echoed back and usable in the status lookup. Not unique. |
Request example
curl -X POST "https://cpaas.studio/api/voice/v1/click2call" \
-H "X-API-KEY: cpk_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Idempotency-Key: 9d1f-4a2c-agent-42" \
-d "did_id=812" \
-d "agent_number=9526071065" \
-d "customer_number=9812345678" \
-d "reference=lead-4471"
<?php
$ch = curl_init('https://cpaas.studio/api/voice/v1/click2call');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-KEY: cpk_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'Idempotency-Key: 9d1f-4a2c-agent-42',
'Content-Type: application/json',
],
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
'did_id' => 812,
'agent_number' => '9526071065',
'customer_number' => '9812345678',
'reference' => 'lead-4471',
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Success response (data)
{
"uid": "CC7Q2M4X8A1B",
"event_id": "c2c-AB12CD34EF",
"reference": "lead-4471",
"status": "submitted",
"disposition": null,
"agent_number": "9526071065",
"customer_number": "9812345678",
"ring_time": 20,
"duration_seconds": null,
"billsec": null,
"billing_status": "pending",
"billable_units": null,
"recording_available": false,
"submitted_at": "2026-09-11T10:20:30+00:00",
"answered_at": null,
"completed_at": null,
"created_at": "2026-09-11T10:20:30+00:00"
}
Errors
| Code | Status | When |
|---|---|---|
C2C_DID_INVALID |
422 | did_id is unknown, not your account's, inactive, or not Click to Call-eligible. |
C2C_NUMBER_INVALID |
422 | agent_number or customer_number will not normalize for your account. |
C2C_LOOPBACK |
422 | agent_number and customer_number are the same. |
C2C_CONCURRENT_CALL |
409 | A Click to Call is already in flight on your account, at or above your plan's concurrency limit. The refused attempt is still logged — its uid is in error.details. |
BILLING_NO_ACTIVE_PLAN |
402 | Your account has no active Click to Call plan. |
BILLING_PLAN_QUOTA_EXHAUSTED |
402 | Your plan's quota is used up and it does not allow overdraft. |
REQ_IDEMPOTENCY_KEY_CONFLICT |
409 | The Idempotency-Key header matches a prior request but this body is different. |
SYS_PROVIDER_ERROR |
502 | The operator rejected the call or was unreachable — safe to retry. |
REQ_VALIDATION_FAILED |
422 | Any field-level rule failure not covered by a more specific code above. Sending a field this endpoint does not accept — ring_time, for example — lands here too, with REQ_FIELD_NOT_PERMITTED against that field in error.details. |
Notes
- A 202 means accepted, not connected and not billed. Billing is charged once, after the CDR, only on a call that actually connected — poll the status endpoint for the outcome.
- What a call costs depends on your assigned plan's pulse setting: per call ("full call"), or per 30/60-second pulse of connected time (billsec — ring time is never charged). A plan on unlimited (validity) billing is not charged per call.
- On a plan with overdraft enabled, quota is not checked before dialing, because the amount is not known until the call ends — it may go negative, and the shortfall is settled automatically the next time a plan is assigned. Without overdraft, a request is refused up front once the quota is used up.
- The number of Click to Call requests that may be in flight per account at once is set by your assigned plan (falling back to a platform default). A request over that limit is refused with 409 C2C_CONCURRENT_CALL — the attempt is still recorded and still has a uid, so it appears in your logs.
- An optional Idempotency-Key request header replays the original call on an identical retry within 24 hours; a different body under the same key is a conflict, never a silent no-op.
- One request is one call. There is no batching, no scheduling, and no recipient list.
- Ring time is a fixed platform setting (20 seconds) and is not settable per call. It is returned in every response for reference, but sending a ring_time field is rejected rather than ignored, so a value you set can never silently fail to apply.
Need more context? See Getting started for authentication, the response envelope, and the full error-code reference.