For the complete documentation index, see llms.txt. This page is also available as Markdown.

API - VoIP Webhook

Public route used by external telephony providers/centrals to send already completed calls to SprintHub.

For each received event, SprintHub:

  • identifies the lead by phone (or creates a new lead, if the number is unknown);

  • logs the call in the call history (voip_history), visible in the CRM;

  • logs the event in the lead timeline (voip.call_incoming or voip.call_outgoing).


Endpoint

Replace CLIENT_NAME with the instance name (e.g.: myclient). The parameter ?i= is what identifies the client's database and must always be present in the URL configured in the provider.


Authentication

Authentication is optional and defined per instance:

Situation
Behavior

Client without secret configured

The endpoint accepts the request without additional validation

Client with secret configured

It is mandatory to send the secret, otherwise the response is 401 unauthorized

When the secret is active, send it in one of two ways:

or

The secret configuration (voip_webhook_secret) is done by the SprintHub team in the client's instance.


Request body

The body is an envelope with two fields: event and data.

Field
Type
Required
Description

event

string

yes

Only value accepted today: "call"

data

object

yes

Completed call data (table below)

Fields of data

Field
Type
Required
Description

user

number

yes

SprintHub user ID who made/received the call. Must exist in the instance

leadPhone

string

yes

Contact phone number, with country code. Non-numeric characters are removed

type

string

yes

INCOMING (received) or OUTGOING (made)

status

string

yes

COMPLETE (answered) or INCOMPLETE (not answered)

duration

number

yes

Duration in seconds. Use 0 for unanswered calls

record

boolean

yes

Indicates whether the call was recorded in the central

service

string

yes

Provider/central identifier (up to 32 characters). E.g.: "twilio"

lead

number

no

Lead ID, if already known. If omitted, the lead is resolved by phone

leadName

string

no

Contact name (up to 64 characters)

userName

string

no

Operator name (up to 64 characters)

callId

string

no

Call ID in the provider (up to 64 characters). Used for reconciliation

description

string

no

Free-form note about the call (up to 1000 characters)

Fields not listed above are rejected: any extra property results in 400 invalid_body.

Example — received and answered call

Example — made and unanswered call

Example with cURL


Postman Collection

File: voip_webhook_postman_collection.json — import into Postman at Import > File.

Before running, adjust the collection variables:

Variable
Description

baseUrl

API URL (e.g.: https://api.sprinthub.app)

instance

Instance name, used in the ?i=

secret

Webhook secret. Leave empty if the instance does not use a secret

userId

ID of an existing user in the instance

leadPhone

Phone number used in tests

service

Provider identifier sent in service

leadId

Fill in only for the request "with lead provided"

The collection has two folders:

  • Success — answered incoming call, unanswered outgoing call, minimal payload, with lead provided and with masked phone number. Each request validates 201/msg: created and stores the returned ID in the variable historyId.

  • Errors — the cases of 400 (missing required field, event invalid, invalid enum, extra field) and the 401 invalid secret.

Requests in the folder Success create real records in the call history and may create the lead from the provided phone number. Use a test instance. The callId is generated with {{$timestamp}} so each submission is unique.


What SprintHub does with the event

  1. Validates the body — format, types and required fields.

  2. Normalizes the phone number — removes everything that is not a digit from leadPhone.

  3. Resolves the lead:

    • if lead was sent, it is used directly;

    • otherwise, it looks for an existing lead by the phone, mobile and WhatsApp fields (with handling of the 9th digit in Brazilian numbers);

    • if it does not find one, it creates a new lead with source VoIP, using the WhatsApp name and photo when the number has an active account, or the phone number itself as the name.

  4. Registers the call in the call history and returns the generated ID.

  5. Registers in the lead timeline the event voip.call_incoming or voip.call_outgoing, with operator, phone, status, duration, callId and service.

If lead resolution/creation fails, the call is still recorded — just without a lead link (and, in that case, without a timeline event).


Responses

Code
Body
Meaning

201

{ "msg": "created", "id": 123 }

Call recorded. id is the identifier in the call history

400

{ "msg": "invalid_body", "err": { ... } }

Invalid body: missing required field, wrong type or extra field

401

{ "msg": "unauthorized" }

Secret configured in the instance and not sent (or sent incorrectly)

500

{ "msg": "failed_voip_webhook", "err": "..." }

Failed to save the call. It can be resent

The field err of the 400 brings the validation detail, useful for debugging the integration:


Best practices

  • Send one event per completed call, after the end — the webhook does not handle progress events (ringing, answered, etc.).

  • There is no deduplication by callId: resending the same event creates a new record in the history. Always send callId to allow reconciliation and avoid unnecessary resends.

  • Resend only on error 500 or timeout, with progressive wait between attempts. Since the failure may occur after the call has been recorded, a resend can generate a duplicate record — use the callId to identify.

  • duration in seconds, always an integer.

  • record: true only indicates that there is a recording in the central; the audio is not sent or attached by this endpoint.

  • Respect text field size limits (userName, leadName and callId up to 64; service up to 32; description up to 1000). Larger values may be truncated or cause an error 500.

  • Automation: the trigger "received call" (leadPhoneCall, event received) recognizes the calls INCOMING received by this webhook. The filter by operator number does not apply, since the webhook does not send that number.

  • This endpoint does not generate credit usage or automatic transcription — it only records the call history and the event on the lead.

Last updated

Was this helpful?