Skip to main content

API reference

Pagination and filtering

limit and offset, page size caps and the filters that exist.

List endpoints return results one page at a time. You choose the page with limit and offset. This page covers paging, the few filters that exist and the fixed sort order. Each resource page lists its own filters: finns, deployments, audiences, phone numbers, wallet.

Limit and offset

limit sets the page size. offset sets how many records to skip.

curl "https://api.hirefinn.ai/api/v1/finns?limit=200&offset=0" \
  -H "Authorization: Bearer $FINN_API_KEY"
{
  "success": true,
  "data": [
    { "id": "8f14e45f-ceea-467a-9f6a-1c0e5b2a77d1", "name": "Renewals" },
    { "id": "1c0e5b2a-77d1-4a6e-9b21-8e4c5f7d2a10", "name": "Inbound support" }
  ],
  "limit": 200,
  "offset": 0
}
FieldTypeDescription
dataarrayThe records on this page.
limitintegerThe page size Finn actually used, after applying the rules below.
offsetintegerThe offset Finn actually used.
totalintegerOnly on GET /audiences/{audience_id}/contacts: the number of contacts in the audience.

Responses have no cursor, no has_more and, except for contacts, no total. If a page has fewer records than limit, it's the last page.

Page sizes

EndpointDefault limitMaximum limitOrder
GET /finns50200Newest first
GET /deployments50200Newest first
GET /phone_numbers50200Newest first
GET /audiences50200Newest first
GET /wallet/transactions50200Newest first
GET /audiences/{audience_id}/contacts1001000Order in the contact file

GET /voices and GET /phone_numbers/available return the whole result in one response and ignore limit and offset. There's no endpoint that lists calls. To read a call, use GET /calls/{call_uuid} with an ID you got from POST /calls or from a webhook.

Finn adjusts out-of-range values instead of rejecting them:

You sendFinn uses
limit above the maximumThe maximum
limit below 11
limit=0, an empty value, or a value that isn't a numberThe default
A negative offset, or one that isn't a number0

The response always shows the limit and offset Finn actually used. Read them from the response rather than assuming you got what you asked for.

Iterating a full collection

async function listAllFinns(apiKey: string): Promise<unknown[]> {
  const results: unknown[] = [];
  const limit = 200;

  for (let offset = 0; ; offset += limit) {
    const url = new URL("https://api.hirefinn.ai/api/v1/finns");
    url.searchParams.set("limit", String(limit));
    url.searchParams.set("offset", String(offset));

    const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
    if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);

    const page = await res.json();
    results.push(...page.data);
    if (page.data.length < page.limit) return results;
  }
}
import requests

BASE = "https://api.hirefinn.ai/api/v1"

def list_all_finns(api_key):
    results, offset, limit = [], 0, 200
    while True:
        res = requests.get(
            f"{BASE}/finns",
            headers={"Authorization": f"Bearer {api_key}"},
            params={"limit": limit, "offset": offset},
            timeout=30,
        )
        res.raise_for_status()
        page = res.json()
        results.extend(page["data"])
        if len(page["data"]) < page["limit"]:
            return results
        offset += page["limit"]

Offset paging can go wrong in two ways:

  • Records shift while you page. Lists are newest first, so if a record is created while you're paging, every older record moves down one place. You'll see one record twice at a page boundary. Deleting or archiving a record has the opposite effect: you'll skip one. Remove duplicates by id when you combine pages.
  • Large walks use up your read limit. A 429 partway through leaves you with partial results unless you retry. Use the maximum limit. See rate limits.

Filtering

Filters are query parameters, and only a few endpoints have them:

EndpointParameterValues
GET /deploymentsstatusOne lowercase status, for example in_progress. Exact match.
GET /deploymentscall_typeinbound or outbound
GET /wallet/transactionstypesUp to 20 comma-separated transaction types (letters a to z and _)

If you send a filter value that doesn't fit the format, you get 400 invalid_request. Finn ignores parameters it doesn't recognize, so check the spelling of filter names. A typo silently returns unfiltered results. There are no date-range filters.

Sorting

Lists are always sorted in the order shown in the Page sizes table. There's no sort parameter, and Finn ignores one if you send it. If you need a different order, fetch the records and sort them yourself.

See API conventions for the request and response rules that apply to every endpoint, and errors for every error code.