Skip to main content

API reference

Audiences

Contact lists and their members.

Beta. This endpoint is not final. Field names and response shapes can change before general availability.

What an audience is

An audience is a named list of contacts. Each contact holds a phone number plus whatever variables your agent needs to personalize the call. Outbound campaigns take an audience as their target, so the audience is where the dialing list and the per-contact merge data live together.

You reference the same variables in your prompt that you store on the contact. See agents-variables for how those get substituted at call time, and outbound-campaigns for how an audience is consumed by a campaign.

The audience object

FieldTypeNotes
idstringAudience identifier.
namestringHuman-readable label. Not guaranteed unique.
contact_countintegerMembers currently in the list. Updated asynchronously after bulk writes, so it can lag.
created_atstringISO 8601 timestamp.
updated_atstringISO 8601 timestamp.

Whether audiences carry a description or free-form tag field is not yet settled. Do not depend on one.

The contact object

FieldTypeNotes
idstringContact identifier, scoped to the audience.
phone_numberstringE.164 including country code. Required.
namestringOptional display name.
variablesobjectFlat string-to-string map merged into the agent prompt.
created_atstringISO 8601 timestamp.

variables is flat. Nested objects and arrays are not read by the prompt substitution layer, and passing them may be rejected outright rather than flattened.

List audiences

curl https://api.hirefinn.ai/v1/audiences \
  -H "Authorization: Bearer $FINN_API_KEY"
{
  "data": [
    {
      "id": "aud_8Kq2vRn4",
      "name": "July renewals",
      "contact_count": 1420,
      "created_at": "2026-07-02T09:14:00Z",
      "updated_at": "2026-07-21T16:03:11Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Paging follows the cursor rules in api-pagination.

Create an audience

curl -X POST https://api.hirefinn.ai/v1/audiences \
  -H "Authorization: Bearer $FINN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: aud-create-2026-07-30-a" \
  -d '{"name": "July renewals"}'

Creating an audience does not add contacts. A new audience comes back with contact_count: 0.

Add contacts

Contacts are added in batches against the audience.

curl -X POST https://api.hirefinn.ai/v1/audiences/aud_8Kq2vRn4/contacts \
  -H "Authorization: Bearer $FINN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: aud-8Kq2vRn4-batch-01" \
  -d '{
    "contacts": [
      {
        "phone_number": "+14155550142",
        "name": "Dana Reyes",
        "variables": { "plan": "Pro", "renewal_date": "2026-08-14" }
      },
      {
        "phone_number": "+919820055512",
        "name": "Arun Mehta",
        "variables": { "plan": "Starter", "renewal_date": "2026-08-02" }
      }
    ]
  }'

The batch is partially accepted. Valid rows land, invalid rows come back in rejected with a reason. A 200 does not mean every row was stored, so read rejected on every call.

{
  "accepted": 1,
  "rejected": [
    {
      "index": 1,
      "phone_number": "+919820055512",
      "reason": "duplicate_in_audience"
    }
  ]
}

Common rejection reasons:

ReasonCause
invalid_phone_numberNot parseable as E.164. Local formats and missing country codes fail here.
duplicate_in_audienceThe number already exists in this audience. Duplicates across different audiences are allowed.
variables_not_flatA value in variables was an object or array.

Batch size limits are enforced but the exact ceiling is not documented here. Keep batches modest and split large imports rather than pushing a single call as far as it will go.

List contacts

const res = await fetch(
  "https://api.hirefinn.ai/v1/audiences/aud_8Kq2vRn4/contacts?limit=100",
  { headers: { Authorization: `Bearer ${process.env.FINN_API_KEY}` } }
);

if (!res.ok) {
  throw new Error(`List contacts failed: ${res.status} ${await res.text()}`);
}

const body = await res.json();
for (const contact of body.data) {
  console.log(contact.phone_number, contact.variables);
}

Remove a contact

curl -X DELETE https://api.hirefinn.ai/v1/audiences/aud_8Kq2vRn4/contacts/con_5Tz9 \
  -H "Authorization: Bearer $FINN_API_KEY"

Removing a contact does not cancel a call already queued for that contact by a running campaign. Pause the campaign first if you need the removal to take effect on this run.

Delete an audience

curl -X DELETE https://api.hirefinn.ai/v1/audiences/aud_8Kq2vRn4 \
  -H "Authorization: Bearer $FINN_API_KEY"

Deleting an audience that a running campaign references is rejected. Stop the campaign, then delete. Deletion removes the contacts too, and it is not reversible from the API.

Failure modes worth planning for

StatusWhen
400Malformed body, or variables containing nested values.
404Audience or contact ID does not exist, or belongs to another workspace.
409Audience is in use by an active campaign.
429Rate limited. See api-rate-limits.

Error bodies follow api-errors. Retry semantics and the Idempotency-Key header behave as described in api-idempotency. Retrying a contact batch without an idempotency key can double-insert rows that are not exact duplicates, so send the key on every write.