Skip to main content

API reference

Deployments

Campaigns and inbound bindings.

Beta. Every endpoint on this page is live and documented as shipped. Shapes can still change before general availability.

Overview

A deployment puts a Finn to work on a phone number.

  • An outbound deployment dials every contact in an audience from one of your numbers. It starts dialing as soon as it is created.
  • An inbound deployment connects a number to a Finn so the Finn answers calls to that number. This is how you assign a number to a Finn; there is no separate assign endpoint.

Deploying sets the Finn's status to live. Stopping the deployment sets it back to draft.

Base URL: https://api.hirefinn.ai/api/v1. Auth: Authorization: Bearer finn_live_.... See authentication.

You need three IDs, all from your organization:

IDFrom
finn_idapi-finns
phone_number_idapi-phone-numbers
audience_id (outbound only)api-audiences

Deployments are attributed to the user who created the API key. That user must still be a member of your organization, otherwise creating a deployment returns 409 api_key_owner_required; create a new key from the dashboard.

Scheduling a deployment for later, pausing and resuming are not available in the API. A request with a schedule returns 422 schedule_not_supported.

Endpoints

MethodPathRate limit (per API key)
POST/deployments10 per minute, shared with POST /deployments/inbound
POST/deployments/inboundSame create bucket
POST/deployments/{id}/stop30 per minute, shared with POST /deployments/inbound/{finn_id}/stop
POST/deployments/inbound/{finn_id}/stopSame stop bucket
GET/deployments300 per minute, shared with GET /deployments/{id} and GET /wallet/transactions
GET/deployments/{id}Same read bucket

The deployment object

{
  "id": "0e8a4c71-9b2d-4f36-a5e1-7c3d9b2f6a10",
  "finn_id": "8f14e45f-ceea-467a-9f6a-1c0e5b2a77d1",
  "audience_id": "c2d9e7a4-51b8-4e0f-8a63-9f1d2b7c5e48",
  "phone_number_id": "6b1f0c2e-3d4a-4f5b-9c8d-2e7a1b9f4c03",
  "call_type": "outbound",
  "status": "in_progress",
  "from_number": "+918035731234",
  "number_pool": null,
  "max_parallel_calls": 1,
  "schedule": null,
  "total_calls": 120,
  "completed_calls": 37,
  "recording_enabled": false,
  "created_at": "2026-10-02T10:15:00.000Z",
  "updated_at": "2026-10-02T10:41:12.000Z"
}
FieldTypeNotes
idstringUUID.
finn_idstring or nullThe Finn.
audience_idstring or nullThe audience. null for inbound.
phone_number_idstring or nullThe number. null when max_parallel_calls is above 1: the number is in number_pool instead.
call_typestringoutbound or inbound.
statusstringSee Status.
from_numberstring or nullThe number dialed from (outbound) or answered on (inbound). null when max_parallel_calls is above 1: the number is in number_pool instead.
number_poolstring[] or nullNumbers used for parallel calling. Set when max_parallel_calls is above 1, in place of from_number and phone_number_id; null otherwise. A deployment created through the API has one number in the pool: the phone_number_id you sent.
max_parallel_callsinteger or nullConcurrent calls. 1, or null right after creation, for a deployment dialing one call at a time.
scheduleobject or null{ "date", "start_time", "timezone" } for deployments scheduled in the dashboard. Always null for deployments created through the API.
total_callsinteger or nullCalls the deployment plans to make, normally the audience size. 0 for inbound.
completed_callsinteger or nullCalls finished so far.
recording_enabledbooleanWhether the deployment's calls are recorded. See Call recording.
created_atstringISO 8601.
updated_atstringISO 8601.

Status

StatusMeaning
pendingCreated, starting up.
in_progress, active, runningLive.
pausedPaused from the dashboard.
scheduledWaiting for a start time (dashboard only).
completedAn outbound deployment that has dialed its whole audience.
stoppedStopped by you or the dashboard. Inbound deployments end as stopped, never completed.
errorFinn could not run it.

Treat this as the common set, not a closed enum, and handle unknown values.

Create an outbound deployment

POST /deployments

FieldTypeRequiredNotes
finn_idstringyesUUID of a Finn in your organization.
phone_number_idstringyesUUID of a number in your organization to dial from.
audience_idstringyesUUID of an audience in your organization.
max_parallel_callsintegerno1 to 5. Default 1. Above 1, the number places up to that many calls at once.
recording_enabledbooleannotrue to turn on the call recording add-on. Default false. Billable; see Call recording.
scheduleobjectnoNot supported. Any non-null value returns 422 schedule_not_supported.
curl -X POST https://api.hirefinn.ai/api/v1/deployments \
  -H "Authorization: Bearer $FINN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "finn_id": "8f14e45f-ceea-467a-9f6a-1c0e5b2a77d1",
    "phone_number_id": "6b1f0c2e-3d4a-4f5b-9c8d-2e7a1b9f4c03",
    "audience_id": "c2d9e7a4-51b8-4e0f-8a63-9f1d2b7c5e48",
    "max_parallel_calls": 3,
    "recording_enabled": true
  }'

Response 201 Created:

{
  "success": true,
  "data": {
    "id": "0e8a4c71-9b2d-4f36-a5e1-7c3d9b2f6a10",
    "finn_id": "8f14e45f-ceea-467a-9f6a-1c0e5b2a77d1",
    "audience_id": "c2d9e7a4-51b8-4e0f-8a63-9f1d2b7c5e48",
    "phone_number_id": null,
    "call_type": "outbound",
    "status": "pending",
    "from_number": null,
    "number_pool": ["+918035731234"],
    "max_parallel_calls": 3,
    "schedule": null,
    "total_calls": 0,
    "completed_calls": 0,
    "recording_enabled": true,
    "created_at": "2026-10-02T10:15:00.000Z",
    "updated_at": "2026-10-02T10:15:00.000Z"
  }
}

With max_parallel_calls above 1, as in this example, phone_number_id and from_number are null and the number you sent is in number_pool. To match a parallel deployment to a number, compare number_pool with the number's phone_number.

In rare cases data contains only id. Read the full object with GET /deployments/{id}.

This starts real calls immediately. Each call is billed to your wallet. Before creating the deployment, Finn checks that the wallet holds at least half the audience's size in one-minute calls (minimum one), and returns 402 insufficient_credits if it does not. Check your balance with api-wallet.

Other conditions:

  • The Finn must not already have a live deployment (pending, in_progress, active or running, inbound or outbound). Otherwise 409 deployment_already_active with the existing deployment_id.
  • The number must not be held by another deployment that has not ended (409 phone_number_in_use), must not be pending or cancelled (404 phone_number_not_found), and must not be isolated after a spam check (409 phone_number_isolated). A number whose deployment has ended as completed, stopped or error is freed, so you can deploy it again right away.
  • The audience must have a contact list with at least one contact (422 audience_not_ready) and must not be dynamic (422 audience_not_supported).

There is no idempotency key. A retry after a timeout usually returns 409 deployment_already_active because the first request already started the deployment; check with GET /deployments before retrying.

Results arrive per call. Read them with api-calls or receive call.completed webhooks; see api-webhooks.

Create an inbound deployment

POST /deployments/inbound

Connects a number to a Finn so the Finn answers calls to it.

FieldTypeRequiredNotes
finn_idstringyesUUID of a Finn in your organization.
phone_number_idstringyesUUID of a number in your organization.
recording_enabledbooleannotrue to turn on the call recording add-on. Default false. Billable; see Call recording.
curl -X POST https://api.hirefinn.ai/api/v1/deployments/inbound \
  -H "Authorization: Bearer $FINN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "finn_id": "8f14e45f-ceea-467a-9f6a-1c0e5b2a77d1",
    "phone_number_id": "6b1f0c2e-3d4a-4f5b-9c8d-2e7a1b9f4c03"
  }'

Returns 201 Created with the deployment object, call_type inbound and audience_id null.

The number is configured at the carrier to route incoming calls to the Finn. A Finn can have one live inbound deployment, and a number can serve one Finn: otherwise the request returns 409 deployment_already_active or 409 phone_number_in_use. Inbound calls are billed to your wallet as they happen; creating the deployment does not check the balance.

Call recording

Call recording is an add-on you turn on per deployment. It is off for deployments created through the API unless you send "recording_enabled": true when you create an outbound or inbound deployment. The deployment object reports the setting in recording_enabled. The API sets it only at creation; there is no endpoint to change it on an existing deployment.

Recording is a billable add-on. Each answered call on a deployment with recording on is charged once for recording, on top of the call itself, and shows in the wallet ledger as a debit_call_recording entry (api-wallet). Calls that are not answered are not charged for recording. The per-call rate is set for your organization.

Post-call analysis does not depend on the add-on. Answers to the Finn's analysis questions arrive in GET /calls/{call_uuid} (api-calls) and in call.completed webhooks either way. With the add-on on, answered calls are recorded: recording_url in GET /calls/{call_uuid} and in the call.completed webhook is a signed link to the recording, valid for 1 hour. Without it, recording_url is null.

If you record, disclosure rules may apply.

Stop an outbound deployment

POST /deployments/{id}/stop

curl -X POST https://api.hirefinn.ai/api/v1/deployments/0e8a4c71-9b2d-4f36-a5e1-7c3d9b2f6a10/stop \
  -H "Authorization: Bearer $FINN_API_KEY"
{
  "success": true,
  "data": { "id": "0e8a4c71-9b2d-4f36-a5e1-7c3d9b2f6a10", "status": "stopped" }
}

Stops dialing, frees the number and sets the Finn back to draft. The Finn is set to draft even if it still has a live inbound deployment, for example one started in the dashboard. That inbound deployment isn't stopped, but the Finn's status no longer shows live. Works on deployments that are pending, in_progress, active, running, paused or scheduled; a finished deployment returns 409 deployment_not_active. Inbound deployments must be stopped with the inbound endpoint below (409 use_inbound_stop). A stopped deployment cannot be restarted; create a new one.

Stop an inbound deployment

POST /deployments/inbound/{finn_id}/stop

Takes the Finn's ID, not the deployment's, and stops that Finn's live inbound deployment.

curl -X POST https://api.hirefinn.ai/api/v1/deployments/inbound/8f14e45f-ceea-467a-9f6a-1c0e5b2a77d1/stop \
  -H "Authorization: Bearer $FINN_API_KEY"
{
  "success": true,
  "data": {
    "id": "5d2c8f19-7a4e-4b03-b6d1-3e9f0a7c2b84",
    "finn_id": "8f14e45f-ceea-467a-9f6a-1c0e5b2a77d1",
    "status": "stopped"
  }
}

The number stops routing calls to the Finn and is freed. The Finn returns to draft if it has no other live deployment. The number stays rented; release it with api-phone-numbers if you no longer need it.

List deployments

GET /deployments

Newest first.

Query parameterTypeDefaultNotes
statusstringnoneOne lowercase status, for example in_progress.
call_typestringnoneinbound or outbound.
limitinteger501 to 200. Out-of-range values are clamped.
offsetinteger0Number of items to skip.
curl "https://api.hirefinn.ai/api/v1/deployments?call_type=outbound&status=in_progress" \
  -H "Authorization: Bearer $FINN_API_KEY"
{
  "success": true,
  "data": [
    {
      "id": "0e8a4c71-9b2d-4f36-a5e1-7c3d9b2f6a10",
      "finn_id": "8f14e45f-ceea-467a-9f6a-1c0e5b2a77d1",
      "audience_id": "c2d9e7a4-51b8-4e0f-8a63-9f1d2b7c5e48",
      "phone_number_id": "6b1f0c2e-3d4a-4f5b-9c8d-2e7a1b9f4c03",
      "call_type": "outbound",
      "status": "in_progress",
      "from_number": "+918035731234",
      "number_pool": null,
      "max_parallel_calls": 1,
      "schedule": null,
      "total_calls": 120,
      "completed_calls": 37,
      "recording_enabled": false,
      "created_at": "2026-10-02T10:15:00.000Z",
      "updated_at": "2026-10-02T10:41:12.000Z"
    }
  ],
  "limit": 50,
  "offset": 0
}

There is no total count. Page with offset until a page returns fewer than limit items. Deployments archived in the dashboard are not returned.

Retrieve a deployment

GET /deployments/{id}

curl https://api.hirefinn.ai/api/v1/deployments/0e8a4c71-9b2d-4f36-a5e1-7c3d9b2f6a10 \
  -H "Authorization: Bearer $FINN_API_KEY"

Returns { "success": true, "data": { ... } } with one deployment object. Poll it to follow total_calls and completed_calls.

Errors

StatuserrorEndpointWhen
400invalid_requestallAn ID is not a UUID; max_parallel_calls is not an integer from 1 to 5; recording_enabled is not true or false; status or call_type filter is invalid.
401api_key_requiredallNo Bearer finn_live_... key.
401invalid_api_keyallKey unknown or revoked.
402insufficient_creditsoutbound createThe wallet does not cover half the audience in one-minute calls.
404finn_not_foundcreate, inbound stopNo Finn with that ID in your organization.
404phone_number_not_foundcreateNo usable number with that ID: not yours, or pending or cancelled.
404audience_not_foundoutbound createNo active audience with that ID in your organization.
404deployment_not_foundget, stop, inbound stopNo deployment with that ID, or the Finn has no live inbound deployment.
409api_key_owner_requiredcreateThe key's creator is no longer a member of your organization.
409deployment_already_activecreateThe Finn already has a live deployment. Body may include deployment_id.
409phone_number_in_usecreateThe number is held by another deployment that has not ended. Numbers from completed, stopped or error deployments are freed and can be deployed again.
409phone_number_isolatedcreateThe number was isolated after a spam-flag check. Release it in the dashboard first.
409conflictcreateAnother conflict with the current state; see message.
409use_inbound_stopstopThe deployment is inbound.
409deployment_not_activestopThe deployment has already finished or stopped.
422schedule_not_supportedoutbound createA schedule was sent.
422audience_not_supportedoutbound createThe audience is dynamic.
422audience_not_readyoutbound createThe audience has no contact list, or its contact list has no contacts.
422deployment_rejectedcreateFinn rejected the deployment; see message and, when present, errors.
429rate_limitedallOver the bucket's per-minute limit.
500internal_errorallUnexpected server error.
502deployment_failedcreateThe deployment could not be created. Check GET /deployments before retrying.
502stop_failedstop, inbound stopThe deployment could not be stopped. Retry.

Error bodies have the shape { "error": "...", "message": "..." }; internal_error has no message. See api-errors.