ProviderCall

A ProviderCall is an admin-triggered outbound call placed through a specific SIP provider, bypassing normal dialroute selection. It is an audit record that captures the admin’s original request plus the IDs of the Call and Groupcall records produced by the underlying call-creation step.

API Reference: ProviderCall endpoints

Overview

Note

AI Context

  • Complexity: Medium

  • Cost: Chargeable. Each POST /v1/providercalls creates one or more real outbound calls. Billing and outbound rate-limiting apply identically to customer-initiated calls; the admin’s own customer account is charged.

  • Async: Yes. The POST response is a ProviderCall audit record that contains the IDs of the created Call and Groupcall records. Per-call state (dialing / ringing / answered / hangup reason) must be observed via GET https://api.voipbin.net/v1.0/calls/{id} or the normal Call webhooks.

  • Access: Admin-only. Requires PermissionProjectSuperAdmin. Customer-tier users (PermissionCustomerAdmin, PermissionCustomerManager, PermissionCustomerAgent) cannot call this endpoint.

VoIPBIN’s ProviderCall API lets platform super-admins place a real outbound call through a specific SIP provider, forcing the routing decision instead of letting the normal customer / default dialroute merge choose one. Use cases:

  • Provider onboarding. Verify that a newly-configured provider actually accepts calls, routes to the PSTN, and returns a sensible SIP response — before live customer traffic touches it.

  • Routing debugging. When a provider is suspected of misbehaving, isolate it from normal dialroute priority so the admin can exercise it directly.

  • Post-config verification. After changing hostname / tech_prefix / tech_postfix / tech_headers on an existing provider, confirm the new configuration actually works.

The endpoint triggers a call — it does not produce a pass/fail verdict. Admins interpret the resulting Call’s status, hangup reason, and SIP trace themselves.

How ProviderCalls Work

bin-api-manager is a thin gateway: it authenticates, verifies the provider_id exists, and forwards the full request to bin-route-manager. The orchestration happens inside route-manager (which owns the ProviderCall entity):

  1. Optional temp-flow creation — when the admin supplies inline actions without a flow_id, route-manager creates a temporary flow via FlowV1FlowCreate and passes that flow’s id to call-manager. If any downstream step fails, the temp flow is cleaned up.

  2. Server-side metadata construction — two internal keys are attached to the Call:

    • route_provider_ids — tells call-manager / route-manager to return a synthetic dialroute that points at exactly the specified provider, bypassing the normal customer / default merge.

    • skip_source_validation — tells call-manager to preserve the admin-supplied source number verbatim, instead of silently falling back to the customer’s DefaultOutgoingSourceNumberID when the source is not owned by the customer. Necessary because providers commonly reject INVITEs whose From / P-Asserted-Identity doesn’t match a pre-allowlisted caller ID.

  3. Create the underlying Call(s) — route-manager issues CallV1CallsCreate synchronously. Call-manager persists the Call(s), reads route_provider_ids in getDialroutes and forwards them to DialrouteList, honors skip_source_validation in getValidatedSourceForOutgoingCall.

  4. Persist the ProviderCall audit record — route-manager saves the admin’s request info (customer_id, provider_id, flow_id, source, destinations, anonymous) alongside the IDs of the Call and Groupcall records that step 3 produced.

The response is the persisted ProviderCall.WebhookMessage — an atomic record (IDs only, no embedded Call/Groupcall objects, per the VoIPBIN atomic-API rule). Admin retrieves per-call state separately.

Internal-only metadata (not a customer-facing API field)

Call.Metadata is server-side-only on internal trust paths. No customer-facing POST endpoint accepts a metadata field in the request body. Both route_provider_ids and skip_source_validation are built server-side by the admin endpoint (never passed in by clients). The call-manager listen handler rejects unknown metadata keys with HTTP 400, so new keys must be declared in the typed-registry before they can be set.

Note

AI Implementation Hint

After POST /v1/providercalls returns, the ProviderCall record’s call_ids array contains one entry per destination. To observe per-destination outcome, iterate call_ids and call GET https://api.voipbin.net/v1.0/calls/{id} (or subscribe to webhooks) for each. Do not poll the ProviderCall record itself for call state — it is a summary, not a live status snapshot.

Provider Validation

Before the underlying call is created, the handler validates that the supplied provider_id exists and is not soft-deleted (via RouteV1ProviderGet). This fail-fast check prevents the scenario where a Call record is created with metadata pointing at a non-existent provider — route-manager would then return an error at dial-time, leaving behind a dead Call record.

Soft-Delete Semantics

DELETE /v1/providercalls/{id} is a soft-delete — it sets tm_delete on the audit record and returns the deleted ProviderCall object. The underlying Call records referenced by call_ids are not affected. Hard deletion of the historical audit trail is not supported.

Note

AI Implementation Hint

Deleting a ProviderCall is purely an audit-trail operation. If you need to terminate a call that’s currently in progress, use POST /v1/calls/{id}/hangup against the call_ids entry instead — the ProviderCall DELETE does not hang up or cancel anything on the wire.

ProviderCall

ProviderCall

A ProviderCall is a persisted audit record for an admin-triggered call placed through a specific SIP provider. It captures the admin’s original request (customer, provider, flow, source, destinations, anonymous option) plus the identifiers of the calls and groupcalls that were created by the underlying call-creation step. The ProviderCall itself does not embed the full Call/Groupcall records — use the IDs with GET https://api.voipbin.net/v1.0/calls/{id} to observe per-call progress.

{
    "id": "<string>",
    "customer_id": "<string>",
    "provider_id": "<string>",
    "flow_id": "<string>",
    "source": {
        "type": "<string>",
        "target": "<string>",
        "target_name": "<string>"
    },
    "destinations": [
        {
            "type": "<string>",
            "target": "<string>",
            "target_name": "<string>"
        }
    ],
    "anonymous": "<string>",
    "call_ids": ["<string>"],
    "groupcall_ids": ["<string>"],
    "tm_create": "<string>",
    "tm_update": "<string>",
    "tm_delete": "<string>"
}
  • id (UUID): The ProviderCall’s unique identifier. Returned when creating via POST https://api.voipbin.net/v1.0/providercalls or listing via GET https://api.voipbin.net/v1.0/providercalls.

  • customer_id (UUID): The customer the record is attributed to. Set server-side from the authenticated admin’s own customer (from the JWT/accesskey); not settable via the request body.

  • provider_id (UUID): The provider the call was forced through. Obtained from the id field of GET https://api.voipbin.net/v1.0/providers.

  • flow_id (UUID): The flow executed after the destination answered. 00000000-0000-0000-0000-000000000000 when no flow was attached (inline actions or no post-answer logic).

  • source (Object, nullable): The admin-supplied source address (caller ID). Preserved verbatim — the normal customer-ownership check on the source number is bypassed for this flow so a provider-allowlisted caller ID reaches the carrier unchanged. null if the admin did not supply one.

  • destinations (Array of Object, minItems: 1): The admin-supplied dial targets. One Call or Groupcall is created per destination, depending on destination type.

  • anonymous (enum string): The anonymous caller-ID option requested. See Anonymous.

  • call_ids (Array of UUID): IDs of the Call records that the call-creation step produced. Use each ID with GET https://api.voipbin.net/v1.0/calls/{id} to observe per-call progress.

  • groupcall_ids (Array of UUID): IDs of any Groupcall records that were produced (when a destination resolved to a group-type address). Use each ID with GET https://api.voipbin.net/v1.0/groupcalls/{id}.

  • tm_create (string, ISO 8601): Timestamp when the ProviderCall record was created.

  • tm_update (string, ISO 8601): Timestamp of the last update to the record.

  • tm_delete (string, ISO 8601): Timestamp when the ProviderCall was soft-deleted. Remains null until a DELETE call is made.

Note

AI Implementation Hint

The ProviderCall is a summary record — the actual per-call state (dialing, ringing, answered, hangup reason) lives on each Call referenced by call_ids. Do not poll the ProviderCall itself for call progress. Instead, iterate call_ids and poll GET https://api.voipbin.net/v1.0/calls/{id} (or listen for the corresponding webhooks) to determine outcome.

Example

{
    "id": "b7d1c0f6-9a2e-4b3f-8e2a-1c7d5b8a9e0f",
    "customer_id": "6a93f71e-8b2d-4e5f-9a1c-2d3e4f5a6b7c",
    "provider_id": "4dbeabd6-f397-4375-95d2-a38411e07ed1",
    "flow_id": "00000000-0000-0000-0000-000000000000",
    "source": {
        "type": "tel",
        "target": "+14155551234",
        "target_name": ""
    },
    "destinations": [
        {
            "type": "tel",
            "target": "+821012345678",
            "target_name": ""
        }
    ],
    "anonymous": "auto",
    "call_ids": ["9f8e7d6c-5b4a-3c2d-1e0f-abcdef012345"],
    "groupcall_ids": [],
    "tm_create": "2026-04-21 23:15:00.000000",
    "tm_update": "2026-04-21 23:15:00.000000",
    "tm_delete": null
}

Anonymous

Controls whether the outbound caller ID is anonymized on the INVITE that leaves VoIPbin.

Value

Description

yes

Always send anonymous caller ID (RFC 3323 Privacy header). The real source number is carried in the P-Asserted-Identity header (RFC 3325) so carriers can route and bill correctly while the called party sees “Anonymous”.

no

Never anonymize. The source number is sent as-is.

auto

Default behavior. Today this resolves the same as no; in the future it will inherit from the incoming channel’s SIP Privacy header when the outbound call is a relay of an inbound leg.

""

Empty string. Equivalent to auto.

Tutorial

Before placing a providercall, you need:

  • A platform super-admin authentication token. Obtain one by logging in as a user with the PermissionProjectSuperAdmin permission. Customer-tier tokens are rejected with 403.

  • A provider ID (UUID). Obtain one from GET https://api.voipbin.net/v1.0/providers. The provider must exist and must not be soft-deleted.

  • A source address — typically a phone number in E.164 format that the provider’s carrier has pre-allowlisted as an acceptable From / P-Asserted-Identity. Because this endpoint skips the normal customer-ownership check on the source, the admin is trusted to supply a value the provider will accept.

  • At least one destination address — typically a phone number in E.164 format.

  • (Optional) A flow ID (UUID) from GET https://api.voipbin.net/v1.0/flows if you want a specific flow to execute after the destination answers.

  • (Optional) A list of inline actions (see the Flow Action struct) to execute post-answer. A temporary flow is auto-created for the call if you supply actions without a flow_id.

Note

AI Implementation Hint

The POST /v1/providercalls endpoint creates real, billable outbound calls. One Call record is created per entry in destinations. The admin’s own customer is charged. Existing outbound rate-limiting applies. Do not call this endpoint in automated CI — it will generate real PSTN traffic.

Place a providercall

The minimum required body is provider_id + at least one destination. source is strongly recommended (without it the call leaves with no caller ID, which most providers reject).

$ curl -k --location --request POST 'https://api.voipbin.net/v1.0/providercalls?token=<YOUR_AUTH_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "provider_id": "4dbeabd6-f397-4375-95d2-a38411e07ed1",
        "source": {
            "type": "tel",
            "target": "+14155551234"
        },
        "destinations": [
            {
                "type": "tel",
                "target": "+821012345678"
            }
        ],
        "anonymous": "auto"
    }'

{
    "id": "b7d1c0f6-9a2e-4b3f-8e2a-1c7d5b8a9e0f",
    "customer_id": "6a93f71e-8b2d-4e5f-9a1c-2d3e4f5a6b7c",
    "provider_id": "4dbeabd6-f397-4375-95d2-a38411e07ed1",
    "flow_id": "00000000-0000-0000-0000-000000000000",
    "source": {"type": "tel", "target": "+14155551234", "target_name": ""},
    "destinations": [{"type": "tel", "target": "+821012345678", "target_name": ""}],
    "anonymous": "auto",
    "call_ids": ["9f8e7d6c-5b4a-3c2d-1e0f-abcdef012345"],
    "groupcall_ids": [],
    "tm_create": "2026-04-21 23:15:00.000000",
    "tm_update": "2026-04-21 23:15:00.000000",
    "tm_delete": null
}

Save call_ids[0] as call_id and poll it for per-call state.

Place a providercall with inline actions

If you want the call to execute a short post-answer sequence (e.g., play a TTS prompt and hang up), supply inline actions instead of a flow_id. A temporary flow is created for you.

$ curl -k --location --request POST 'https://api.voipbin.net/v1.0/providercalls?token=<YOUR_AUTH_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "provider_id": "4dbeabd6-f397-4375-95d2-a38411e07ed1",
        "source": {"type": "tel", "target": "+14155551234"},
        "destinations": [{"type": "tel", "target": "+821012345678"}],
        "actions": [
            {"type": "answer"},
            {
                "type": "talk",
                "option": {
                    "text": "This is a provider verification call.",
                    "language": "en-US",
                    "gender": "female"
                }
            },
            {"type": "hangup"}
        ]
    }'

Observe call outcome

The ProviderCall record is an audit summary — it does not update as the call progresses. Use the standard call API with each ID in call_ids.

$ curl -k --location --request GET 'https://api.voipbin.net/v1.0/calls/9f8e7d6c-5b4a-3c2d-1e0f-abcdef012345?token=<YOUR_AUTH_TOKEN>'

{
    "id": "9f8e7d6c-5b4a-3c2d-1e0f-abcdef012345",
    "status": "progressing",
    "hangup_reason": "",
    "metadata": {
        "route_provider_ids": ["4dbeabd6-f397-4375-95d2-a38411e07ed1"],
        "skip_source_validation": true
    },
    ...
}

Note

AI Implementation Hint

If the call never reaches progressing and ends with hangup_reason: failed immediately, the provider rejected the INVITE. Common causes: hostname unreachable, authentication failure on the provider’s end, source number not on the provider’s allowlist, or destination number not supported by the provider.

Get list of providercalls

Returns records scoped to the authenticated admin’s own customer. Optional provider_id filter narrows to a single provider.

$ curl -k --location --request GET 'https://api.voipbin.net/v1.0/providercalls?token=<YOUR_AUTH_TOKEN>&provider_id=4dbeabd6-f397-4375-95d2-a38411e07ed1'

{
    "result": [
        {
            "id": "b7d1c0f6-9a2e-4b3f-8e2a-1c7d5b8a9e0f",
            "provider_id": "4dbeabd6-f397-4375-95d2-a38411e07ed1",
            "call_ids": ["9f8e7d6c-5b4a-3c2d-1e0f-abcdef012345"],
            ...
        }
    ],
    "next_page_token": "2026-04-21 23:15:00.000000"
}

Get detail of a providercall

$ curl -k --location --request GET 'https://api.voipbin.net/v1.0/providercalls/b7d1c0f6-9a2e-4b3f-8e2a-1c7d5b8a9e0f?token=<YOUR_AUTH_TOKEN>'

Delete (soft) a providercall

Removes the audit record from list results. Does not affect the underlying Call records.

$ curl -k --location --request DELETE 'https://api.voipbin.net/v1.0/providercalls/b7d1c0f6-9a2e-4b3f-8e2a-1c7d5b8a9e0f?token=<YOUR_AUTH_TOKEN>'

{
    "id": "b7d1c0f6-9a2e-4b3f-8e2a-1c7d5b8a9e0f",
    "tm_delete": "2026-04-22 00:00:00.000000",
    ...
}

Troubleshooting

  • 403 Forbidden:
    • Cause: Token belongs to a customer-tier user. ProviderCalls require PermissionProjectSuperAdmin.

    • Fix: Log in as a platform super-admin or use an admin access key.

  • 400 Bad Request — provider not found:
    • Cause: The supplied provider_id does not exist, or has been soft-deleted.

    • Fix: List providers with GET /v1/providers and choose a current ID.

  • Call immediately hangs up (``hangup_reason: failed``):
    • Cause: Provider rejected the INVITE. Common reasons: source not on allowlist, destination unsupported, provider auth failed, hostname unreachable.

    • Fix: Review the provider’s acceptance rules. Try a source number the provider is known to accept. Cross-check the provider’s SIP server health via GET /v1/providers/{id} (health_status field).

  • Call reports ``no_answer`` / ``busy``:
    • Cause: Signaling reached the provider and the destination, but the far-end did not answer or rejected the call.

    • Fix: This usually means the provider is working correctly — the destination phone’s state is the issue, not the routing.