API reference / Integrations

Integrations

The Integrations endpoints of the Voiceland AI API, with parameters, schemas and curl examples.

Last updated:

GET /v1/agents/{name}/integrations#

Supported integrations as seen from an agent. Every integration kind with its state. Every current kind is project-wide (scope: project): the PBX (yeastar_crm) and the CRM (hubspot) are configured once for the project under /integrations; this list shows the same rows for convenience. Writes on this path for a project-wide kind act on the project row.

Parameters

Name In Type Required Description
name path string Yes Agent name.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/agents/{name}/integrations" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "items": [
    {
      "auth_modes": [
        "bearer",
        "oauth2"
      ],
      "calls_logged": 17,
      "capabilities": [
        "contact_lookup",
        "contact_create",
        "call_journal",
        "call_popup",
        "recording_link",
        "ops_trigger"
      ],
      "category": "pbx",
      "client_id": "vlc_2ffa3f973bfcbb5aa82fafea",
      "configured": true,
      "contact_lookups": 42,
      "create_unknown_contacts": true,
      "created_at": "2026-09-14T10:00:00Z",
      "description": "Connect a Yeastar P-Series Cloud Edition PBX through its custom CRM template: callers are matched against the project's contacts, unknown callers can be added, every finished call is journalled to the contact, and operations agents with a \"call ended\" trigger run on it.",
      "enabled": true,
      "endpoints": {
        "authorize": "https://api.voiceland.ai/oauth/authorize",
        "calls": "https://api.voiceland.ai/v1/integrations/yeastar/calls",
        "contacts": "https://api.voiceland.ai/v1/integrations/yeastar/contacts",
        "template": "https://api.voiceland.ai/v1/integrations/yeastar_crm/template.xml",
        "token": "https://api.voiceland.ai/v1/integrations/oauth/token"
      },
      "kind": "yeastar_crm",
      "last_seen_at": "2026-09-15T06:45:31Z",
      "logo": "/v1/integrations/yeastar_crm/logo.svg",
      "name": "Yeastar P-Series Cloud PBX",
      "order": 1,
      "redirect_uris": [
        "https://example.com/integration/callback/api/crm/2df2ad9bbc084115bde6924892756da9/"
      ],
      "scope": "project",
      "secret_hint": "…gWc4",
      "vendor": "Yeastar"
    }
  ]
}

DELETE /v1/agents/{name}/integrations/{kind}#

Remove an integration. Deletes the OAuth client; every token it issued stops working. Journalled calls are kept.

Parameters

Name In Type Required Description
name path string Yes Agent name.
kind path string Yes Integration kind.

Responses

Code Description
204 Removed.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X DELETE "https://api.voiceland.ai/v1/agents/{name}/integrations/{kind}" \
  -H "Authorization: Bearer VL_API_KEY"

PUT /v1/agents/{name}/integrations/{kind}#

Enable or configure an integration. The first call with enabled: true mints the OAuth client and answers 201 with client_secret, which is shown exactly once: store it in the other system at once. Later calls reconfigure (redirect_uris for the OAuth2 authorization-code flow, create_unknown_contacts to let the PBX add callers it does not find, authorize_base_url when the consent page lives on your own console host). Setting enabled: false revokes every token the client holds.

Parameters

Name In Type Required Description
name path string Yes Agent name.
kind path string Yes Integration kind.

Request body

application/json Schema: IntegrationRequest

Field Type Required Description
authorize_base_url string
create_unknown_contacts boolean
enabled boolean
redirect_uris array of string

Responses

Code Description
200 Reconfigured (201 on first enable, with client_secret).
400 invalid_redirect_uri (absolute https, no fragment), too_many_redirect_uris (max 5).
401 Missing or invalid API key.
404 agent_not_found, unknown_integration.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X PUT "https://api.voiceland.ai/v1/agents/{name}/integrations/{kind}" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "create_unknown_contacts": true,
  "enabled": true,
  "redirect_uris": [
    "https://example.com/integration/callback/api/crm/2df2ad9bbc084115bde6924892756da9/"
  ]
}'

A successful response returns a IntegrationView.

Example response

{
  "auth_modes": [
    "bearer",
    "oauth2"
  ],
  "calls_logged": 17,
  "capabilities": [
    "contact_lookup",
    "contact_create",
    "call_journal",
    "call_popup",
    "recording_link",
    "ops_trigger"
  ],
  "category": "pbx",
  "client_id": "vlc_2ffa3f973bfcbb5aa82fafea",
  "client_secret": "vls_Q1w2E3r4T5y6U7i8O9p0A1s2D3f4G5h6J7k8L9z0X1c2V3b4",
  "configured": true,
  "contact_lookups": 42,
  "create_unknown_contacts": true,
  "created_at": "2026-09-14T10:00:00Z",
  "description": "Connect a Yeastar P-Series Cloud Edition PBX through its custom CRM template: callers are matched against the project's contacts, unknown callers can be added, every finished call is journalled to the contact, and operations agents with a \"call ended\" trigger run on it.",
  "enabled": true,
  "endpoints": {
    "authorize": "https://api.voiceland.ai/oauth/authorize",
    "calls": "https://api.voiceland.ai/v1/integrations/yeastar/calls",
    "contacts": "https://api.voiceland.ai/v1/integrations/yeastar/contacts",
    "template": "https://api.voiceland.ai/v1/integrations/yeastar_crm/template.xml",
    "token": "https://api.voiceland.ai/v1/integrations/oauth/token"
  },
  "kind": "yeastar_crm",
  "last_seen_at": "2026-09-15T06:45:31Z",
  "logo": "/v1/integrations/yeastar_crm/logo.svg",
  "name": "Yeastar P-Series Cloud PBX",
  "order": 1,
  "redirect_uris": [
    "https://example.com/integration/callback/api/crm/2df2ad9bbc084115bde6924892756da9/"
  ],
  "scope": "project",
  "secret_hint": "…gWc4",
  "vendor": "Yeastar"
}

POST /v1/agents/{name}/integrations/{kind}/authorize#

Grant access (OAuth2 consent). The consent step of the authorization-code flow, called by the console after the signed-in user allowed the request: mints a single-use code (10 minutes) bound to the client and to a registered redirect_uri and returns the URL to send the browser to. With one registered URI, redirect_uri may be omitted.

Parameters

Name In Type Required Description
name path string Yes Agent name.
kind path string Yes Integration kind.

Request body

application/json

Responses

Code Description
200 Success.
400 redirect_uri_mismatch.
401 Missing or invalid API key.
404 not_configured: enable the integration first.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X POST "https://api.voiceland.ai/v1/agents/{name}/integrations/{kind}/authorize" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "redirect_uri": "https://example.com/integration/callback/api/crm/2df2ad9bbc084115bde6924892756da9/",
  "state": "8f1c"
}'

Example response

{
  "expires_in": 600,
  "redirect_url": "https://example.com/integration/callback/api/crm/2df2ad9bbc084115bde6924892756da9/?code=vic_…&state=8f1c"
}

GET /v1/agents/{name}/integrations/{kind}/events#

What the other system sent. The calls the PBX journalled for this agent, newest first.

Parameters

Name In Type Required Description
name path string Yes Agent name.
kind path string Yes Integration kind.
limit query integer Max rows (default 50, max 500).

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/agents/{name}/integrations/{kind}/events" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "items": [
    {
      "agent": "front-desk",
      "callee_name": "Front desk",
      "callee_number": "401",
      "caller_name": "Maria Papadopoulou",
      "caller_number": "+306972605774",
      "contact_id": "ct-3d60ba7619c2a4f1",
      "contact_number": "+306972605774",
      "description": "Call: 15/09/2026 09:45:24 Incoming Call from Maria Papadopoulou<+306972605774> to Front desk<401> 00:00:06",
      "direction": "inbound",
      "duration_raw": "00:00:06",
      "duration_sec": 6,
      "external_id": "1789454724",
      "id": "ic-9a1b2c3d4e5f6071",
      "kind": "yeastar_crm",
      "received_at": "2026-09-15T06:45:31Z",
      "recording": true,
      "recording_url": "https://example.com/api/v1.0/crm/recording?secret=…",
      "started_at": "2026-09-15T06:45:24Z",
      "started_raw": "15/09/2026 09:45:24",
      "status": "Incoming Call",
      "subject": "Extension Call"
    }
  ]
}

GET /v1/agents/{name}/integrations/{kind}/requests#

What the other system actually sent. Every request the other system sent to the integration endpoints, as it arrived, with the answer it got: method, path, query and headers (an allow-list; the Authorization header as its scheme only), the body and the answer (both capped at 16 KB), the status, the time taken and what it produced. It is the log the call journal cannot be: a lookup that matched nobody, a create that was refused, a journal rejected as invalid and an authentication that failed all appear here and nowhere else. Credentials are masked before the row is written. Rows are kept 30 days.

Parameters

Name In Type Required Description
name path string Yes Agent name.
kind path string Yes Integration kind.
limit query integer Max rows (default 50, max 500).
outcome query string Only ok, rejected (4xx) or failed (5xx).
scenario query string Only auth, contact_lookup, contact_create, call_journal or users.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/agents/{name}/integrations/{kind}/requests" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "items": [
    {
      "agent": "_project",
      "body": "{\"CallId\":\"1727000000\",\"CallerNumber\":\"+302101234567\",\"CalleeNumber\":\"401\",\"Direction\":\"Inbound\",\"Duration\":\"00:00:42\"}",
      "body_bytes": 142,
      "client_id": "vlc_f02fdf34fc14827aea43c66d",
      "contact_id": "ct-91ab20",
      "duration_ms": 38,
      "event_id": "ic-3b77e1",
      "headers": {
        "Authorization": "Bearer •••",
        "Content-Type": "application/json",
        "User-Agent": "Yeastar-PBX/83.16.0.29"
      },
      "id": "ir-9f3a2c",
      "kind": "yeastar_crm",
      "method": "POST",
      "outcome": "ok",
      "path": "/v1/integrations/yeastar/calls",
      "received_at": "2026-09-23T10:15:03Z",
      "remote_ip": "203.0.113.10",
      "scenario": "call_journal",
      "status": 201
    }
  ],
  "retention_days": 30
}

POST /v1/agents/{name}/integrations/{kind}/rotate-secret#

Rotate the client secret. Mints a new secret (returned once) and revokes every token issued under the old one.

Parameters

Name In Type Required Description
name path string Yes Agent name.
kind path string Yes Integration kind.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X POST "https://api.voiceland.ai/v1/agents/{name}/integrations/{kind}/rotate-secret" \
  -H "Authorization: Bearer VL_API_KEY"

A successful response returns a IntegrationView.

Example response

{
  "auth_modes": [
    "bearer",
    "oauth2"
  ],
  "calls_logged": 17,
  "capabilities": [
    "contact_lookup",
    "contact_create",
    "call_journal",
    "call_popup",
    "recording_link",
    "ops_trigger"
  ],
  "category": "pbx",
  "client_id": "vlc_2ffa3f973bfcbb5aa82fafea",
  "client_secret": "vls_Q1w2E3r4T5y6U7i8O9p0A1s2D3f4G5h6J7k8L9z0X1c2V3b4",
  "configured": true,
  "contact_lookups": 42,
  "create_unknown_contacts": true,
  "created_at": "2026-09-14T10:00:00Z",
  "description": "Connect a Yeastar P-Series Cloud Edition PBX through its custom CRM template: callers are matched against the project's contacts, unknown callers can be added, every finished call is journalled to the contact, and operations agents with a \"call ended\" trigger run on it.",
  "enabled": true,
  "endpoints": {
    "authorize": "https://api.voiceland.ai/oauth/authorize",
    "calls": "https://api.voiceland.ai/v1/integrations/yeastar/calls",
    "contacts": "https://api.voiceland.ai/v1/integrations/yeastar/contacts",
    "template": "https://api.voiceland.ai/v1/integrations/yeastar_crm/template.xml",
    "token": "https://api.voiceland.ai/v1/integrations/oauth/token"
  },
  "kind": "yeastar_crm",
  "last_seen_at": "2026-09-15T06:45:31Z",
  "logo": "/v1/integrations/yeastar_crm/logo.svg",
  "name": "Yeastar P-Series Cloud PBX",
  "order": 1,
  "redirect_uris": [
    "https://example.com/integration/callback/api/crm/2df2ad9bbc084115bde6924892756da9/"
  ],
  "scope": "project",
  "secret_hint": "…gWc4",
  "vendor": "Yeastar"
}

GET /v1/agents/{name}/integrations/{kind}/template.xml#

Download the template for the other system. For yeastar_crm: the custom CRM template XML, pre-filled with this deployment's endpoints, to upload under Integrations > CRM > Template Management on the PBX. ?auth=bearer (default) authenticates with the client credentials and needs no browser step; ?auth=oauth2 uses the authorization-code flow through the console's consent page.

Parameters

Name In Type Required Description
name path string Yes Agent name.
kind path string Yes Integration kind.
auth query string bearer (default) or oauth2.

Responses

Code Description
200 application/xml attachment.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/agents/{name}/integrations/{kind}/template.xml" \
  -H "Authorization: Bearer VL_API_KEY"

GET /v1/httpactions#

List HTTP actions. Reusable HTTP request templates your agents can call.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/httpactions" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "items": []
}

POST /v1/httpactions#

Create an HTTP action. Creates a reusable, parameterised HTTP request. Reference secrets with ${secret:NAME} and inputs with ${var}.

Request body

application/json Schema: Action

Field Type Required Description
body any JSON body; string values support substitution. Use null for GET/DELETE.
created_at string (date-time)
description string
headers map of string Request headers; values support ${var} / ${secret:name}.
id string Yes Tenant-scoped slug; stable, referenced from flows.
inputs array of ActionInput Parameters the model fills when invoking the action; each name is a ${name} placeholder.
method string Yes HTTP method: GET, POST, PUT, PATCH, or DELETE.
name string Yes Human-readable label.
query map of string Query parameters; values support ${var} / ${secret:name}.
timeout_s integer Per-request timeout in seconds (1 to 30, default 10).
updated_at string (date-time)
url string Yes Request URL; supports ${var} and ${secret:name}.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X POST "https://api.voiceland.ai/v1/httpactions" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "headers": {
    "Authorization": "Bearer ${secret:crm_token}"
  },
  "id": "lookup-customer",
  "inputs": [
    {
      "name": "phone",
      "required": true,
      "type": "string"
    }
  ],
  "method": "GET",
  "name": "Lookup customer by phone",
  "url": "https://example.com/customers?phone=${phone}"
}'

Example response

{
  "id": "lookup-customer",
  "method": "GET"
}

DELETE /v1/httpactions/{id}#

Delete an HTTP action. Deletes an action.

Parameters

Name In Type Required Description
id path string Yes Action id.

Responses

Code Description
204 Deleted.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X DELETE "https://api.voiceland.ai/v1/httpactions/{id}" \
  -H "Authorization: Bearer VL_API_KEY"

GET /v1/httpactions/{id}#

Get an HTTP action. Returns one action by id.

Parameters

Name In Type Required Description
id path string Yes Action id.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/httpactions/{id}" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "id": "lookup-customer",
  "method": "GET"
}

PUT /v1/httpactions/{id}#

Update an HTTP action. Replaces an action; the id in the path wins.

Parameters

Name In Type Required Description
id path string Yes Action id.

Request body

application/json Schema: Action

Field Type Required Description
body any JSON body; string values support substitution. Use null for GET/DELETE.
created_at string (date-time)
description string
headers map of string Request headers; values support ${var} / ${secret:name}.
id string Yes Tenant-scoped slug; stable, referenced from flows.
inputs array of ActionInput Parameters the model fills when invoking the action; each name is a ${name} placeholder.
method string Yes HTTP method: GET, POST, PUT, PATCH, or DELETE.
name string Yes Human-readable label.
query map of string Query parameters; values support ${var} / ${secret:name}.
timeout_s integer Per-request timeout in seconds (1 to 30, default 10).
updated_at string (date-time)
url string Yes Request URL; supports ${var} and ${secret:name}.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X PUT "https://api.voiceland.ai/v1/httpactions/{id}" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "headers": {
    "Authorization": "Bearer ${secret:crm_token}"
  },
  "id": "lookup-customer",
  "inputs": [
    {
      "name": "phone",
      "required": true,
      "type": "string"
    }
  ],
  "method": "GET",
  "name": "Lookup customer by phone",
  "url": "https://example.com/customers?phone=${phone}"
}'

Example response

{
  "id": "lookup-customer"
}

GET /v1/httpflows#

List HTTP flows. Ordered chains of actions.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/httpflows" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "items": []
}

POST /v1/httpflows#

Create an HTTP flow. Creates an ordered chain of actions with per-step variable extraction.

Request body

application/json Schema: Flow

Field Type Required Description
created_at string (date-time)
description string
id string Yes
inputs array of FlowInput Variables the flow receives.
name string Yes
outputs array of FlowOutput Variables the flow hands back; each must be assigned by some step.
steps array of FlowStep Yes The ordered actions to run, with extract rules per step.
updated_at string (date-time)

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X POST "https://api.voiceland.ai/v1/httpflows" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "order-status",
  "inputs": [
    {
      "name": "phone",
      "required": true,
      "type": "string"
    }
  ],
  "name": "Order status",
  "outputs": [
    {
      "name": "order_id"
    }
  ],
  "steps": [
    {
      "action_id": "lookup-customer",
      "extract": [
        {
          "from": "data.id",
          "var": "order_id"
        }
      ]
    }
  ]
}'

Example response

{
  "id": "order-status"
}

DELETE /v1/httpflows/{id}#

Delete an HTTP flow. Deletes a flow.

Parameters

Name In Type Required Description
id path string Yes Flow id.

Responses

Code Description
204 Deleted.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X DELETE "https://api.voiceland.ai/v1/httpflows/{id}" \
  -H "Authorization: Bearer VL_API_KEY"

GET /v1/httpflows/{id}#

Get an HTTP flow. Returns one flow by id.

Parameters

Name In Type Required Description
id path string Yes Flow id.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/httpflows/{id}" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "id": "order-status"
}

PUT /v1/httpflows/{id}#

Update an HTTP flow. Replaces a flow; the id in the path wins.

Parameters

Name In Type Required Description
id path string Yes Flow id.

Request body

application/json Schema: Flow

Field Type Required Description
created_at string (date-time)
description string
id string Yes
inputs array of FlowInput Variables the flow receives.
name string Yes
outputs array of FlowOutput Variables the flow hands back; each must be assigned by some step.
steps array of FlowStep Yes The ordered actions to run, with extract rules per step.
updated_at string (date-time)

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X PUT "https://api.voiceland.ai/v1/httpflows/{id}" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "id": "order-status",
  "inputs": [
    {
      "name": "phone",
      "required": true,
      "type": "string"
    }
  ],
  "name": "Order status",
  "outputs": [
    {
      "name": "order_id"
    }
  ],
  "steps": [
    {
      "action_id": "lookup-customer",
      "extract": [
        {
          "from": "data.id",
          "var": "order_id"
        }
      ]
    }
  ]
}'

Example response

{
  "id": "order-status"
}

POST /v1/httpflows/{id}/execute#

Run a flow. Executes a flow with the supplied inputs and returns the collected variables + per-step audit. A failed step returns 502 with a partial result.

Parameters

Name In Type Required Description
id path string Yes Flow id.

Request body

application/json

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X POST "https://api.voiceland.ai/v1/httpflows/{id}/execute" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "inputs": {
    "phone": "+30693XXXXXXX"
  }
}'

Example response

{
  "steps": [],
  "vars": {
    "eta": "tomorrow",
    "order_id": "4471"
  }
}

GET /v1/integrations#

Integrations catalog with the project-wide state. Every supported integration with its state for the project. yeastar_crm (the PBX) carries its OAuth client, redirect URIs, endpoints and activity; hubspot (the CRM) its token state, schedule and policies. logo is a public brand mark at /v1/integrations/{kind}/logo.svg.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/integrations" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "items": [
    {
      "auth_modes": [
        "bearer",
        "oauth2"
      ],
      "calls_logged": 17,
      "capabilities": [
        "contact_lookup",
        "contact_create",
        "call_journal",
        "call_popup",
        "recording_link",
        "ops_trigger"
      ],
      "category": "pbx",
      "client_id": "vlc_2ffa3f973bfcbb5aa82fafea",
      "configured": true,
      "contact_lookups": 42,
      "create_unknown_contacts": true,
      "created_at": "2026-09-14T10:00:00Z",
      "description": "Connect a Yeastar P-Series Cloud Edition PBX through its custom CRM template: callers are matched against the project's contacts, unknown callers can be added, every finished call is journalled to the contact, and operations agents with a \"call ended\" trigger run on it.",
      "enabled": true,
      "endpoints": {
        "authorize": "https://api.voiceland.ai/oauth/authorize",
        "calls": "https://api.voiceland.ai/v1/integrations/yeastar/calls",
        "contacts": "https://api.voiceland.ai/v1/integrations/yeastar/contacts",
        "template": "https://api.voiceland.ai/v1/integrations/yeastar_crm/template.xml",
        "token": "https://api.voiceland.ai/v1/integrations/oauth/token"
      },
      "kind": "yeastar_crm",
      "last_seen_at": "2026-09-15T06:45:31Z",
      "logo": "/v1/integrations/yeastar_crm/logo.svg",
      "name": "Yeastar P-Series Cloud PBX",
      "order": 1,
      "redirect_uris": [
        "https://example.com/integration/callback/api/crm/2df2ad9bbc084115bde6924892756da9/"
      ],
      "scope": "project",
      "secret_hint": "…gWc4",
      "vendor": "Yeastar"
    },
    {
      "auth_modes": [
        "private_app_token"
      ],
      "capabilities": [
        "contact_pull",
        "contact_push",
        "push_on_create",
        "conflict_policy"
      ],
      "category": "crm",
      "configured": true,
      "conflict_policy": "merge",
      "created_at": "2026-09-18T10:00:00Z",
      "enabled": true,
      "has_token": true,
      "kind": "hubspot",
      "last_pull_at": "2026-09-19T08:00:04Z",
      "last_run_at": "2026-09-19T08:00:04Z",
      "logo": "/v1/integrations/hubspot/logo.svg",
      "name": "HubSpot CRM",
      "next_pull_at": "2026-09-19T08:30:04Z",
      "order": 2,
      "portal_id": "424242",
      "pull_interval_min": 30,
      "push_interval_min": 0,
      "push_mode": "missing_only",
      "push_on_create": true,
      "scope": "project",
      "vendor": "HubSpot"
    }
  ]
}

DELETE /v1/integrations/{kind}#

Remove a project integration. Deletes the configuration (the PBX's OAuth client, or the CRM's stored token). Journalled calls and synced contacts are kept.

Parameters

Name In Type Required Description
kind path string Yes yeastar_crm or hubspot.

Responses

Code Description
204 Removed.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X DELETE "https://api.voiceland.ai/v1/integrations/{kind}" \
  -H "Authorization: Bearer VL_API_KEY"

PUT /v1/integrations/{kind}#

Configure a project integration. For yeastar_crm the body is the PBX request: the first call with enabled: true mints the OAuth client and answers 201 with client_secret (shown once); later calls set redirect_uris, create_unknown_contacts, authorize_base_url; enabled: false revokes every token. For hubspot: token is the private-app access token (scopes crm.objects.contacts.read and crm.objects.contacts.write), write-only and verified against HubSpot before it is stored (400 hubspot_auth otherwise); pull_interval_min / push_interval_min are 0 (off) or at least 10; conflict_policy: merge (default), hubspot_wins, local_wins, create_new; push_mode: missing_only (default) or force_all; enabled: true needs a token.

Parameters

Name In Type Required Description
kind path string Yes yeastar_crm or hubspot.

Request body

application/json Schema: ProjectIntegrationRequest

Field Type Required Description
conflict_policy string
enabled boolean
pull_interval_min integer
push_interval_min integer
push_mode string
push_on_create boolean
token string

Responses

Code Description
200 Saved (201 on first configuration).
400 hubspot_auth, token_required, interval_too_short, invalid_policy, invalid_push_mode, invalid_redirect_uri, too_many_redirect_uris.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
502 hubspot_unreachable.
5XX Server or upstream error.

Example request

curl -X PUT "https://api.voiceland.ai/v1/integrations/{kind}" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "conflict_policy": "merge",
  "enabled": true,
  "pull_interval_min": 30,
  "push_interval_min": 0,
  "push_mode": "missing_only",
  "push_on_create": true,
  "token": "pat-eu1-…"
}'

A successful response returns a ProjectIntegrationView.

Example response

{
  "auth_modes": [
    "private_app_token"
  ],
  "capabilities": [
    "contact_pull",
    "contact_push",
    "push_on_create",
    "conflict_policy"
  ],
  "category": "crm",
  "configured": true,
  "conflict_policy": "merge",
  "created_at": "2026-09-18T10:00:00Z",
  "enabled": true,
  "has_token": true,
  "kind": "hubspot",
  "last_pull_at": "2026-09-19T08:00:04Z",
  "last_run_at": "2026-09-19T08:00:04Z",
  "logo": "/v1/integrations/hubspot/logo.svg",
  "name": "HubSpot CRM",
  "next_pull_at": "2026-09-19T08:30:04Z",
  "order": 2,
  "portal_id": "424242",
  "pull_interval_min": 30,
  "push_interval_min": 0,
  "push_mode": "missing_only",
  "push_on_create": true,
  "scope": "project",
  "vendor": "HubSpot"
}

POST /v1/integrations/{kind}/authorize#

Grant the PBX access (OAuth2 consent). The consent step of the authorization-code flow, called by the console after the signed-in user allowed the request: mints a single-use code bound to the client and to a registered redirect_uri and returns the URL to send the browser to.

Parameters

Name In Type Required Description
kind path string Yes yeastar_crm.

Request body

application/json

Responses

Code Description
200 Success.
400 redirect_uri_mismatch.
401 Missing or invalid API key.
404 not_configured: enable the integration first.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X POST "https://api.voiceland.ai/v1/integrations/{kind}/authorize" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "redirect_uri": "https://example.com/integration/callback/api/crm/2df2ad9bbc084115bde6924892756da9/",
  "state": "8f1c"
}'

Example response

{
  "expires_in": 600,
  "redirect_url": "https://example.com/integration/callback/api/crm/2df2ad9bbc084115bde6924892756da9/?code=vic_…&state=8f1c"
}

GET /v1/integrations/{kind}/events#

What the PBX sent. The calls the PBX journalled for the project, newest first.

Parameters

Name In Type Required Description
kind path string Yes yeastar_crm.
limit query integer Max rows (default 50, max 500).

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/integrations/{kind}/events" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "items": [
    {
      "agent": "front-desk",
      "callee_name": "Front desk",
      "callee_number": "401",
      "caller_name": "Maria Papadopoulou",
      "caller_number": "+306972605774",
      "contact_id": "ct-3d60ba7619c2a4f1",
      "contact_number": "+306972605774",
      "description": "Call: 15/09/2026 09:45:24 Incoming Call from Maria Papadopoulou<+306972605774> to Front desk<401> 00:00:06",
      "direction": "inbound",
      "duration_raw": "00:00:06",
      "duration_sec": 6,
      "external_id": "1789454724",
      "id": "ic-9a1b2c3d4e5f6071",
      "kind": "yeastar_crm",
      "received_at": "2026-09-15T06:45:31Z",
      "recording": true,
      "recording_url": "https://example.com/api/v1.0/crm/recording?secret=…",
      "started_at": "2026-09-15T06:45:24Z",
      "started_raw": "15/09/2026 09:45:24",
      "status": "Incoming Call",
      "subject": "Extension Call"
    }
  ]
}

GET /v1/integrations/{kind}/requests#

What the PBX actually sent. Every request the other system sent to the integration endpoints, as it arrived, with the answer it got: method, path, query and headers (an allow-list; the Authorization header as its scheme only), the body and the answer (both capped at 16 KB), the status, the time taken and what it produced. It is the log the call journal cannot be: a lookup that matched nobody, a create that was refused, a journal rejected as invalid and an authentication that failed all appear here and nowhere else. Credentials are masked before the row is written. Rows are kept 30 days.

Parameters

Name In Type Required Description
kind path string Yes yeastar_crm.
limit query integer Max rows (default 50, max 500).
outcome query string Only ok, rejected (4xx) or failed (5xx).
scenario query string Only auth, contact_lookup, contact_create, call_journal or users.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/integrations/{kind}/requests" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "items": [
    {
      "agent": "_project",
      "body": "{\"CallId\":\"1727000000\",\"CallerNumber\":\"+302101234567\",\"CalleeNumber\":\"401\",\"Direction\":\"Inbound\",\"Duration\":\"00:00:42\"}",
      "body_bytes": 142,
      "client_id": "vlc_f02fdf34fc14827aea43c66d",
      "contact_id": "ct-91ab20",
      "duration_ms": 38,
      "event_id": "ic-3b77e1",
      "headers": {
        "Authorization": "Bearer •••",
        "Content-Type": "application/json",
        "User-Agent": "Yeastar-PBX/83.16.0.29"
      },
      "id": "ir-9f3a2c",
      "kind": "yeastar_crm",
      "method": "POST",
      "outcome": "ok",
      "path": "/v1/integrations/yeastar/calls",
      "received_at": "2026-09-23T10:15:03Z",
      "remote_ip": "203.0.113.10",
      "scenario": "call_journal",
      "status": 201
    }
  ],
  "retention_days": 30
}

POST /v1/integrations/{kind}/rotate-secret#

Rotate the PBX client secret. For yeastar_crm: mints a new secret (returned once) and revokes every token issued under the old one.

Parameters

Name In Type Required Description
kind path string Yes yeastar_crm.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X POST "https://api.voiceland.ai/v1/integrations/{kind}/rotate-secret" \
  -H "Authorization: Bearer VL_API_KEY"

A successful response returns a IntegrationView.

Example response

{
  "auth_modes": [
    "bearer",
    "oauth2"
  ],
  "calls_logged": 17,
  "capabilities": [
    "contact_lookup",
    "contact_create",
    "call_journal",
    "call_popup",
    "recording_link",
    "ops_trigger"
  ],
  "category": "pbx",
  "client_id": "vlc_2ffa3f973bfcbb5aa82fafea",
  "client_secret": "vls_Q1w2E3r4T5y6U7i8O9p0A1s2D3f4G5h6J7k8L9z0X1c2V3b4",
  "configured": true,
  "contact_lookups": 42,
  "create_unknown_contacts": true,
  "created_at": "2026-09-14T10:00:00Z",
  "description": "Connect a Yeastar P-Series Cloud Edition PBX through its custom CRM template: callers are matched against the project's contacts, unknown callers can be added, every finished call is journalled to the contact, and operations agents with a \"call ended\" trigger run on it.",
  "enabled": true,
  "endpoints": {
    "authorize": "https://api.voiceland.ai/oauth/authorize",
    "calls": "https://api.voiceland.ai/v1/integrations/yeastar/calls",
    "contacts": "https://api.voiceland.ai/v1/integrations/yeastar/contacts",
    "template": "https://api.voiceland.ai/v1/integrations/yeastar_crm/template.xml",
    "token": "https://api.voiceland.ai/v1/integrations/oauth/token"
  },
  "kind": "yeastar_crm",
  "last_seen_at": "2026-09-15T06:45:31Z",
  "logo": "/v1/integrations/yeastar_crm/logo.svg",
  "name": "Yeastar P-Series Cloud PBX",
  "order": 1,
  "redirect_uris": [
    "https://example.com/integration/callback/api/crm/2df2ad9bbc084115bde6924892756da9/"
  ],
  "scope": "project",
  "secret_hint": "…gWc4",
  "vendor": "Yeastar"
}

GET /v1/integrations/{kind}/runs#

Sync history. Runs newest first: direction, trigger (schedule, manual, on_create), status and the counts of contacts read, created, updated, linked, left unchanged and failed. Kept for 30 days.

Parameters

Name In Type Required Description
kind path string Yes hubspot.
limit query integer Max rows (default 50, max 500).

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/integrations/{kind}/runs" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "items": [
    {
      "created": 4,
      "direction": "pull",
      "failed": 0,
      "fetched": 312,
      "finished_at": "2026-09-19T08:00:04Z",
      "id": "run-9a1b2c3d4e5f6071",
      "kind": "hubspot",
      "linked": 2,
      "skipped": 305,
      "started_at": "2026-09-19T08:00:00Z",
      "status": "ok",
      "trigger": "schedule",
      "updated": 1
    }
  ]
}

POST /v1/integrations/{kind}/sync#

Run a sync once. Queues a one-time pull (HubSpot to contacts) or push (contacts to HubSpot); it starts within a minute on one node. 409 sync_in_progress while a run is queued or running; 409 not_enabled before the integration is enabled.

Parameters

Name In Type Required Description
kind path string Yes hubspot.

Request body

application/json

Responses

Code Description
202 Queued.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X POST "https://api.voiceland.ai/v1/integrations/{kind}/sync" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "direction": "pull"
}'

Example response

{
  "direction": "pull",
  "integration": {
    "auth_modes": [
      "private_app_token"
    ],
    "capabilities": [
      "contact_pull",
      "contact_push",
      "push_on_create",
      "conflict_policy"
    ],
    "category": "crm",
    "configured": true,
    "conflict_policy": "merge",
    "created_at": "2026-09-18T10:00:00Z",
    "enabled": true,
    "has_token": true,
    "kind": "hubspot",
    "last_pull_at": "2026-09-19T08:00:04Z",
    "last_run_at": "2026-09-19T08:00:04Z",
    "logo": "/v1/integrations/hubspot/logo.svg",
    "name": "HubSpot CRM",
    "next_pull_at": "2026-09-19T08:30:04Z",
    "order": 2,
    "portal_id": "424242",
    "pull_interval_min": 30,
    "push_interval_min": 0,
    "push_mode": "missing_only",
    "push_on_create": true,
    "scope": "project",
    "vendor": "HubSpot"
  },
  "queued": true
}

GET /v1/integrations/{kind}/template.xml#

Download the PBX template. For yeastar_crm: the custom CRM template XML, pre-filled with this deployment's endpoints and the project's custom fields, to upload under Integrations > CRM > Template Management on the PBX. ?auth=bearer (default) authenticates with the client credentials; ?auth=oauth2 uses the authorization-code flow through the console's consent page.

Parameters

Name In Type Required Description
kind path string Yes yeastar_crm.
auth query string bearer (default) or oauth2.

Responses

Code Description
200 application/xml attachment.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/integrations/{kind}/template.xml" \
  -H "Authorization: Bearer VL_API_KEY"

GET /v1/secrets#

List secrets. Returns your secrets, metadata only, never the value.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/secrets" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "items": [
    {
      "has_value": true,
      "name": "crm_token"
    }
  ]
}

POST /v1/secrets#

Create a secret. Stores an encrypted credential referenced from actions as ${secret:NAME}. Reads never return the value.

Request body

application/json

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X POST "https://api.voiceland.ai/v1/secrets" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "description": "CRM bearer",
  "name": "crm_token",
  "value": "sk-live-abc123"
}'

Example response

{
  "has_value": true,
  "name": "crm_token"
}

DELETE /v1/secrets/{name}#

Delete a secret. Deletes a secret.

Parameters

Name In Type Required Description
name path string Yes Secret name.

Responses

Code Description
204 Deleted.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X DELETE "https://api.voiceland.ai/v1/secrets/{name}" \
  -H "Authorization: Bearer VL_API_KEY"

GET /v1/secrets/{name}#

Get a secret. Returns a secret's metadata. Pass ?reveal=true to also return the plaintext value.

Parameters

Name In Type Required Description
name path string Yes Secret name.
reveal query boolean Return the plaintext value.

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl "https://api.voiceland.ai/v1/secrets/{name}" \
  -H "Authorization: Bearer VL_API_KEY"

Example response

{
  "has_value": true,
  "name": "crm_token"
}

PUT /v1/secrets/{name}#

Update a secret. Replaces a secret's value/description.

Parameters

Name In Type Required Description
name path string Yes Secret name.

Request body

application/json

Responses

Code Description
200 Success.
401 Missing or invalid API key.
4XX Request error (validation, not-found, etc.).
5XX Server or upstream error.

Example request

curl -X PUT "https://api.voiceland.ai/v1/secrets/{name}" \
  -H "Authorization: Bearer VL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "description": "CRM bearer",
  "name": "crm_token",
  "value": "sk-live-def456"
}'

Example response

{
  "has_value": true,
  "name": "crm_token"
}

Schemas#

Action#

A reusable, parameterised HTTP request your agents can call. Placeholders ${var} and ${secret:name} are substituted at run time.

Field Type Required Description
body any JSON body; string values support substitution. Use null for GET/DELETE.
created_at string (date-time)
description string
headers map of string Request headers; values support ${var} / ${secret:name}.
id string Yes Tenant-scoped slug; stable, referenced from flows.
inputs array of ActionInput Parameters the model fills when invoking the action; each name is a ${name} placeholder.
method string Yes HTTP method: GET, POST, PUT, PATCH, or DELETE.
name string Yes Human-readable label.
query map of string Query parameters; values support ${var} / ${secret:name}.
timeout_s integer Per-request timeout in seconds (1 to 30, default 10).
updated_at string (date-time)
url string Yes Request URL; supports ${var} and ${secret:name}.

ActionInput#

Field Type Required Description
description string
name string Yes Parameter name; doubles as the ${name} placeholder.
required boolean
type string string or integer (informational).

Endpoints#

Field Type Required Description
authorize string
calls string Yes
contacts string Yes
template string Yes
token string Yes

Error#

Error envelope returned for non-2xx responses.

Field Type Required Description
error object Yes

ExtractRule#

Field Type Required Description
from string
hint string
var string Yes

Flow#

An ordered chain of actions that passes data step to step.

Field Type Required Description
created_at string (date-time)
description string
id string Yes
inputs array of FlowInput Variables the flow receives.
name string Yes
outputs array of FlowOutput Variables the flow hands back; each must be assigned by some step.
steps array of FlowStep Yes The ordered actions to run, with extract rules per step.
updated_at string (date-time)

FlowInput#

Field Type Required Description
description string
name string Yes
required boolean
type string

FlowOutput#

Field Type Required Description
description string
name string Yes

FlowStep#

Field Type Required Description
action_id string Yes
extract array of ExtractRule

IntegrationRequest#

Field Type Required Description
authorize_base_url string
create_unknown_contacts boolean
enabled boolean
redirect_uris array of string

IntegrationView#

Field Type Required Description
auth_modes array of string Yes
authorize_base_url string
calls_logged integer Yes
capabilities array of string Yes
category string Yes
client_id string
client_secret string
configured boolean Yes
connected_at string (date-time)
connection string Yes
contact_lookups integer Yes
create_unknown_contacts boolean Yes
created_at string (date-time)
description string Yes
docs string
enabled boolean Yes
endpoints Endpoints
kind string Yes
last_seen_at string (date-time)
last_token_at string (date-time)
logo string
name string Yes
order integer Yes
redirect_uris array of string Yes
scope string Yes
secret_hint string
updated_at string (date-time)
vendor string Yes

ProjectIntegrationRequest#

Field Type Required Description
conflict_policy string
enabled boolean
pull_interval_min integer
push_interval_min integer
push_mode string
push_on_create boolean
token string

ProjectIntegrationView#

Field Type Required Description
auth_modes array of string Yes
capabilities array of string Yes
category string Yes
configured boolean Yes
conflict_policy string
created_at string (date-time)
description string Yes
docs string
enabled boolean Yes
has_token boolean Yes
kind string Yes
last_error string
last_pull_at string (date-time)
last_push_at string (date-time)
last_run_at string (date-time)
logo string
name string Yes
next_pull_at string (date-time)
next_push_at string (date-time)
order integer Yes
pending_run string
portal_id string
pull_interval_min integer Yes
push_interval_min integer Yes
push_mode string
push_on_create boolean Yes
scope string Yes
updated_at string (date-time)
vendor string Yes

The console

These pages are read only. The test call, the API keys and the live API reference are in the console, where your account is signed in.

Open the console