Skip to content

API Reference

Fynex provides a REST API for programmatic access. All endpoints require authentication via a Supabase JWT token passed in the Authorization: Bearer <token> header.

Base URL:

  • Development: http://localhost:3001
  • Production: https://api.fynex.solutions

Dispatch

Send Email

POST /api/dispatch/email
ParameterTypeRequiredDescription
account_idUUIDYesTarget account
template_idUUIDNoMessage template to use
action_typestringNoAction type (default: reminder)

Responses: 200 Email sent, 401 Unauthorized, 422 Dispatch blocked.

Send SMS

POST /api/dispatch/sms
ParameterTypeRequiredDescription
account_idUUIDYesTarget account
template_idUUIDNoMessage template to use
action_typestringNoAction type (default: reminder)

Responses: 200 SMS sent, 422 Dispatch blocked.

Send WhatsApp

POST /api/dispatch/whatsapp
ParameterTypeRequiredDescription
account_idUUIDYesTarget account
template_idUUIDNoMessage template to use
action_typestringNoAction type (default: reminder)

Responses: 200 WhatsApp message sent, 422 Dispatch blocked.

Initiate Voice Call

POST /api/dispatch/voice
ParameterTypeRequiredDescription
account_idUUIDYesTarget account
agent_typestringNoai (default) or human
supervisor_user_idUUIDNoUser ID for supervised calls
voice_opening_modestringNoAI only: inherit (default), callee_first, or agent_first. Ignored when agent_type is human.

Responses: 200 Call initiated (includes call_sid and conversation_id), 422 Dispatch blocked, 502 Provider error.

Dispatch Validation

All dispatch endpoints enforce these rules before sending:

  • Opt-out — Blocked if the contact has opted out.
  • Frequency limits — Blocked if max contacts per day/week would be exceeded.
  • Allowed hours — Blocked if outside the organization's configured contact hours.
  • Account paused — Blocked if the account status is paused.

When blocked, the response includes { "blocked": true, "error": "reason" }.

Admin

Phone Numbers

POST /api/admin/phone-numbers
ParameterTypeRequiredDescription
actionstringYessearch, buy, or release
countrystringNoCountry code for search
areaCodestringNoArea code for search
phoneNumberstringNoNumber to buy or release
organizationIdUUIDNoOrganization to assign
channelConfigIdUUIDNoChannel config to update

Email Domains

POST /api/admin/email-domains
ParameterTypeRequiredDescription
actionstringYescreate or verify
domainstringNoDomain name
organizationIdUUIDNoOrganization
channelConfigIdUUIDNoChannel config

ElevenLabs Agent

POST /api/admin/elevenlabs-agent
ParameterTypeRequiredDescription
actionstringYesprovision, status, or set_agent_id
organizationIdUUIDNoOrganization (usually inferred from auth)
agent_idstringFor set_agent_idElevenLabs agent ID to store on the voice channel

provision creates or updates the ConvAI agent and, when a Twilio number is configured but no ElevenLabs phone ID exists yet, registers the number with ElevenLabs automatically. Response may include phone_number_id.

set_agent_id is intended for self-managed orgs that bring their own agent ID.

Voice configuration

GET /api/admin/voice-config
PATCH /api/admin/voice-config

GET returns current defaults: llm, voice_id, voices (per-language map), voice_opening_mode, agent_id, org_language, supported_llms, curated_voices.

PATCH updates organization and voice channel config in one request. Send at least one field:

FieldTypeDescription
llmstringConversational AI LLM id (validated against supported list)
voice_idstringDefault ElevenLabs voice for the org’s primary language
voicesobjectMap of language code → ElevenLabs voice id
voice_opening_modestringcallee_first or agent_first
agent_idstringElevenLabs agent id (e.g. self-managed)

Campaigns

Create Campaign

POST /api/admin/campaigns
ParameterTypeRequiredDescription
namestringYesCampaign name (1-200 chars)
objectivestringNoCampaign objective (max 1000 chars)
strategy_idUUIDNoStrategy to assign (required to activate)
statusstringNoInitial status (default: draft)
start_datestringNoStart date (YYYY-MM-DD)
end_datestringNoEnd date (YYYY-MM-DD, must be >= start)

Responses: 201 Campaign created, 422 Validation failed (invalid dates, missing strategy for active status).

Update Campaign

PATCH /api/admin/campaigns/:id

Accepts the same fields as create. Status transitions are validated:

  • draft → active (requires strategy_id)
  • active → paused (drains pending queue items)
  • active → completed
  • paused → active, paused → completed

Responses: 200 Campaign updated, 422 Invalid status transition or validation error.

Delete Campaign

DELETE /api/admin/campaigns/:id

Removes the campaign. All assigned accounts have their campaign_id set to null. Pending queue items for this campaign are cancelled.

Responses: 200 Campaign deleted.

Campaign Summary

GET /api/admin/campaigns/:id/summary

Returns computed campaign metrics:

FieldTypeDescription
campaignobjectCampaign details (id, name, status, dates)
account_countnumberTotal accounts assigned to this campaign
contacted_countnumberAccounts with at least one interaction
promise_countnumberPayment promises from campaign accounts
total_recoverednumberSum of payments from campaign accounts
contact_ratenumbercontacted_count / account_count (0.0 to 1.0)

Responses: 200 Summary data.

Execution Engine

Pause Execution

POST /api/admin/execution/pause

Pauses automatic dispatch for your organization. Queue items remain but are not processed.

Responses: 200 Execution paused.

Resume Execution

POST /api/admin/execution/resume

Resumes automatic dispatch processing.

Responses: 200 Execution resumed.

Get Queue Status

GET /api/admin/execution/status

Returns counts of pending, processing, completed, failed, and skipped items for today, plus the paused flag.

Enqueue Accounts

POST /api/admin/execution/enqueue
ParameterTypeRequiredDescription
campaign_idUUIDNoLimit to one campaign

Manually triggers account evaluation and enqueuing. Eligible accounts are added to the execution queue. When campaign_id is provided, the campaign must be active and within its date range.

Responses: 200 Returns { enqueued: <count> }, 422 Campaign not active or outside date range.

Bulk Operations

Bulk Account Actions

POST /api/admin/bulk/accounts
ParameterTypeRequiredDescription
account_idsUUID[]YesAccounts to modify (max 500)
actionstringYespause, resume, assign_campaign, assign_strategy, change_status
campaign_idUUIDNoRequired for assign_campaign
strategy_idUUIDNoRequired for assign_strategy
statusstringNoRequired for change_status

Responses: 200 Returns { affected: <count> }.

Billing

Create Checkout Session

POST /api/billing/checkout
ParameterTypeRequiredDescription
price_idstringYesStripe price ID
success_urlURLYesRedirect URL after payment
cancel_urlURLYesRedirect URL on cancel

Responses: 200 Returns { url: "https://checkout.stripe.com/..." }, 503 Billing not configured.

Billing Portal

POST /api/billing/portal
ParameterTypeRequiredDescription
return_urlURLYesRedirect URL after portal

Responses: 200 Returns { url: "https://billing.stripe.com/..." }, 503 Billing not configured.

Notifications

List Notifications

GET /api/notifications

Returns all notifications for the authenticated user, ordered by most recent.

Mark Notification as Read

PATCH /api/notifications/:id/read

Marks a single notification as read.

Mark All as Read

POST /api/notifications/mark-all-read

Marks all unread notifications for the authenticated user as read.

Voice

Get Signed URL

POST /api/voice/signed-url

Returns a signed WebSocket URL for browser-based voice sessions.

ParameterTypeRequiredDescription
organization_idUUIDYesOrganization

Response: { "signedUrl": "wss://..." }

Check Capabilities

POST /api/voice/capabilities

Checks whether an organization is ready to make voice calls (Twilio credentials, ElevenLabs agent, phone number).

ParameterTypeRequiredDescription
organization_idUUIDYesOrganization

Interactions

Recover Voice Transcript

POST /api/interactions/:id/refresh-voice

Fetches the conversation data from ElevenLabs for a voice interaction whose post-call webhook was missed. Updates transcript, disposition, contact result, sentiment, and all analysis metadata. If the strategy step was stuck in waiting_response, it is automatically unblocked.

This endpoint is idempotent — calling it on an interaction that already has a transcript will overwrite it with the latest data from ElevenLabs.

ParameterTypeLocationRequiredDescription
idUUIDpathYesInteraction ID

Responses:

CodeDescription
200Transcript recovered; returns updated interaction
404Interaction not found or wrong organization
422Not a voice interaction, no conversation ID, or call still in progress
502ElevenLabs API fetch failed

Public API v1

The v1 API provides programmatic access for external system integration. Authentication via X-API-Key header or Bearer JWT.

Authentication

MethodHeaderUse case
API KeyX-API-Key: fynex_pk_...Machine-to-machine integrations
JWTAuthorization: Bearer <token>Browser-based access

Accounts

POST /api/v1/accounts

Create or upsert an account. If external_id is provided and matches an existing account, updates it.

ParameterTypeRequiredDescription
external_idstringNoYour system's unique ID for this account
source_systemstringNoLabel for the source system
contactobjectYesContact info (name required, email/phone/whatsapp optional)
total_amountnumberYesTotal debt amount
pending_balancenumberNoDefaults to total_amount
referencestringNoHuman-readable reference number
currencystringNoISO 4217 code (default: ARS)
GET /api/v1/accounts

List accounts with pagination.

ParameterTypeRequiredDescription
limitnumberNoMax results (default 50, max 1000)
offsetnumberNoSkip first N results
statusstringNoFilter by collection_status
external_idstringNoFilter by external_id
GET /api/v1/accounts/:id

Get account by Fynex ID. Use ?by=external_id to look up by external ID instead.

PATCH /api/v1/accounts/:id

Update account fields.

Contacts

POST /api/v1/contacts
GET /api/v1/contacts
GET /api/v1/contacts/:id
PATCH /api/v1/contacts/:id

Same pattern as accounts. Supports upsert by external_id.

Payments

POST /api/v1/payments

Register an external payment. Provide account_id or account_external_id.

Import & Export

POST /api/v1/import

Start async bulk import. Returns { job_id, status }.

GET /api/v1/import/:jobId

Check import job progress.

POST /api/v1/export/accounts

Export accounts as JSON or CSV with filters.

Webhook Subscriptions

POST /api/v1/webhooks
GET /api/v1/webhooks
PATCH /api/v1/webhooks/:id
DELETE /api/v1/webhooks/:id
POST /api/v1/webhooks/:id/test

Manage outbound webhook subscriptions.

Rate Limits

All v1 endpoints: 100 requests per 15 minutes per API key.

Webhooks

These endpoints receive callbacks from external providers. They are not called by client applications.

EndpointProviderValidation
POST /api/webhooks/twilioTwilioHMAC-SHA1 signature
POST /api/webhooks/resendResendSvix HMAC-SHA256
POST /api/webhooks/elevenlabsElevenLabsHMAC-SHA256
POST /api/webhooks/agent-tool-handlerElevenLabsHMAC-SHA256
POST /api/webhooks/stripeStripeStripe signature

System

Health Check

GET /health

Returns { "status": "ok", "timestamp": "..." } when the server is running.