Smart Lists

The Smart Lists API exposes the same dialing configuration used across Sailor. Every request is pinned to the one workspace encoded in the API key; organization and subaccount identifiers are never accepted from the caller.

Use a key with smart_lists:read to inspect lists and members, or smart_lists:write to create, update, clone, delete, and mutate membership.

Create every supported configuration

$curl https://api.sailorhq.io/smart-lists \
> -X POST \
> -H "Authorization: Bearer $SAILOR_API_TOKEN" \
> -H "Idempotency-Key: $SAILOR_REQUEST_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "name": "Fresh inbound leads",
> "description": "New demo requests called first",
> "priority": "highest",
> "max_attempts_per_day": 4,
> "max_attempts_total": 10,
> "min_retry_seconds": 2700,
> "dial_timeout_seconds": 30,
> "next_list_id": null
> }'
FieldBehavior
priorityhighest, high, medium, low, or lowest. Sailor drains the tiers in that order, using its durable deterministic cursor inside a tier. Every eligible listed contact is considered before contacts that are not in a list.
max_attempts_per_dayPer-contact, per-list daily cap. null means unlimited; 0 freezes dispatch.
max_attempts_totalPer-contact, per-list lifetime cap. null means unlimited; 0 freezes dispatch.
min_retry_secondsMinimum time before the same list member is eligible again.
dial_timeout_secondsRing timeout from 15 through 60 seconds in five-second increments.
next_list_idSame-workspace list that receives a member after the total-attempt rule completes. null clears the waterfall.

source, creation timestamps, membership attempt counters, statuses, and dispositions are read-only evidence. They are owned by Sailor’s ingest and scheduler, not writable configuration.

Update, clone, and delete

PATCH /smart-lists/{smartListId} applies only the fields present in the JSON body. Send null for either cap to make it unlimited, or for next_list_id to clear the waterfall.

POST /smart-lists/{smartListId}/clone copies all dialing settings but no members. This avoids accidentally doubling a live dial pool. DELETE /smart-lists/{smartListId} deletes the list and its memberships; calls already in flight retain their immutable call snapshot.

Add existing contacts

Batch operations accept 1–100 existing contacts. Identify each contact by Sailor contact_id or E.164 phone. Sailor resolves the reference only inside the API key’s workspace and stores the canonical contact ID.

$curl https://api.sailorhq.io/smart-lists/$SMART_LIST_ID/members/batch \
> -X POST \
> -H "Authorization: Bearer $SAILOR_API_TOKEN" \
> -H "Idempotency-Key: $SAILOR_REQUEST_KEY" \
> -H "Content-Type: application/json" \
> -d '{"members":[{"contact_id":"00000000-0000-4000-8000-000000000010"},{"phone":"+14165550124"}]}'

The response reports inserted, skipped, and unmatched counts. An already-active membership is skipped. An ID or phone that does not resolve inside this workspace is unmatched; it never resolves from another tenant.

Remove contacts

Use POST /smart-lists/{smartListId}/members/batch-remove to remove members from one list. Use POST /smart-list-members/batch-remove for the same contacts across every active list in this workspace. Both operations are atomic, accept 1–100 references, and return removed, skipped, and unmatched counts.

Pagination and polling

GET /smart-lists and GET /smart-lists/{smartListId}/members use opaque cursor pagination. Pass next_page_token back as page_token without decoding or modifying it. Member reads may filter by status and expose the scheduler-owned attempt count, last attempt, last disposition, schedule time, and status reason.

Polling is safe, but prefer a bounded interval and respect RateLimit, RateLimit-Policy, and Retry-After. Reads are strongly tenant-scoped and do not accept X-Active-Subaccount as an override.

Reliability rules

  • Reuse one Idempotency-Key only for retries of the exact same logical write.
  • A duplicate active list name returns 409 resource_conflict.
  • A missing or cross-workspace list returns a generic 404 or 400; tenant existence is never disclosed.
  • Batch removal is one database mutation, so a partial cross-list removal cannot leak through a worker crash.
  • Priority traversal is restart-safe: the scheduler persists its cursor, resumes without reordering a tenant’s queue, and reaches unlisted contacts only after every eligible listed tier has been traversed.
  • Kixie’s PowerList API exposes contact add/update/remove operations. Sailor additionally exposes complete list resource CRUD, cloning, configuration, pagination, member state, bounded batches, durable idempotency, and least-privilege scopes.
  • Sailor’s five priorities, retry interval, daily and total attempt caps, next-list waterfall, and config-only clone are the Sailor equivalents informed by Kixie’s PowerList setup guide and Next Action guide. Kixie also documents vendor-specific controls Sailor does not implement; Sailor never publishes fictional settings.