---
title: Connect Your Call Flow
excerpt: Authenticate your PBX call flow and query the Smart Routings lookup endpoints, with request parameters, response formats and error codes.
order: 5
---

## Overview

Your call flow talks to Smart Routings with plain HTTP `GET` requests and reads JSON responses. In 3CX, build it with the Call Flow Designer; any PBX whose call flow can send an HTTP request and read a JSON value works the same way.

All URLs below are relative to your workspace API:

```
https://your-workspace.cx-engine.com/api
```

Send `Accept: application/json` on every request, so that errors are also returned as JSON.

Every lookup needs your account, passed as `customer_account` (your CX-Engine account identifier) or `customer_id`.

## Authentication

The lookup endpoints require a Bearer token:

```
Authorization: Bearer {access-token}
```

The token belongs to a CX-Engine user. That user must have access to the account and, in their role, the **Lookup** permission on the resources the call flow queries (**Inbound rules**, **Geographic**, **CTI**).

### CFD token (recommended for call flows)

A CFD token is a long secret designed for call flows. The call flow exchanges it for an access token:

`GET /api/smart-routings/cfd-auth/t/{cfd-token}`

```json
{
  "message": "success",
  "token": "eyJ0eXAiOiJKV1Qi...",
  "expires_at": "2026-10-09T11:42:00+00:00",
  "user": { "id": 12, "name": "Call flows", "...": "..." }
}
```

Use the returned `token` as the Bearer token of the lookups. It carries the `cfd` scope, which only gives access to the lookup endpoints and to survey recording. It is valid for 1 hour: have the call flow exchange the CFD token on each call. Expiring or deleting the CFD token revokes its access tokens immediately.

A CFD token can be restricted to a list of IP addresses (`hosts`). A request from another address gets `403 Host not authorised.`

A CFD token can also have an expiry date (`expires_at`). Once it is past, the exchange answers `404 This token does not exists or has expired.` A token without expiry date never expires.

CFD tokens are created through the API. See [CX-Engine API › Smart Routings](/en/docs/cx-api/smart-routings).

### OAuth token

Any OAuth access token of a user with the `client` scope also works on the lookups. It is required to read [routing contacts](/en/docs/smart-routings/contacts-geographic-routing#querying-contacts-from-a-call-flow), which the `cfd` scope does not cover. See [CX-Engine API › Authentication](/en/docs/cx-api/authentication).

## Inbound rule lookup

Returns the destination of an [inbound rule](/en/docs/smart-routings/inbound-rules) at the current date and time.

`GET /api/smart-routings/call-queues/lookup`

| Parameter | Required | Description |
|---|---|---|
| `customer_account` or `customer_id` | Yes | Your account |
| `queue_id`, `queue_number` or `queue_name` | Yes, one of them | The rule: its ID, its queue number (**Resource** of a queue rule), or its **Name** |
| `day` | No | Date to evaluate, `YYYY-MM-DD`. Defaults to today. |
| `time` | No | Time to evaluate, `HH:MM:SS`. Defaults to now. |

`day` and `time` are read in the timezone of your account. Use them to test a schedule ("what happens on 25 December at 10:00?").

**Example**

```
GET /api/smart-routings/call-queues/lookup?customer_account=ACME&queue_number=800
```

**Response `200` — a time span matches**

```json
{
  "reference": "open",
  "destination": "801",
  "label": null,
  "inherited": false,
  "matched": "time_span,day_of_week"
}
```

**Response `200` — an exception matches**

```json
{
  "reference": "France:christmasDay",
  "destination": "999",
  "label": "Christmas Day",
  "inherited": false,
  "matched": "exception"
}
```

| Field | Description |
|---|---|
| `reference` | Internal reference of the matched time span or exception |
| `destination` | Destination to route the call to. Can be `null` if none was set on the row. |
| `label` | Label of the exception, `null` for a time span |
| `inherited` | `true` when the matched row is defined on the rules group itself |
| `matched` | `exception`, `time_span,date_full` (span on a specific date) or `time_span,day_of_week` (weekly span) |

See [How the destination is chosen](/en/docs/smart-routings/opening-hours#how-the-destination-is-chosen) for the evaluation order.

**Errors**

| Status | Message | Meaning |
|---|---|---|
| `404` | `No destination found matching given parameters.` | No exception or time span matches: the rule is **closed**. Route to your closed message. |
| `404` | `No queue found matching given parameters.` | No **active** rule matches the `queue_*` parameter |
| `404` | `No customer found matching given parameters.` | Unknown account |
| `400` | `Invalid date or time provided.` | `day` or `time` could not be read |
| `403` | | The token's user lacks access to the account or the **Lookup** permission |

> [!WARNING]
> `queue_number` only matches **queue** rules. For a **DID** rule, query by `queue_name` or `queue_id`.

## Geographic lookup

Returns the destinations of a [geographic list](/en/docs/smart-routings/contacts-geographic-routing#geographic-routing) for a caller.

`GET /api/smart-routings/geo/destinations/lookup`

| Parameter | Required | Description |
|---|---|---|
| `customer_account` or `customer_id` | Yes | Your account |
| `list_id` or `list_name` | Yes, one of them | The **Unique identifier** or the **Name** of the list |
| `number` or `zone` | Yes, one of them | The caller number (converted into a zone by the list's geographic model), or a zone directly |

**Example**

```
GET /api/smart-routings/geo/destinations/lookup?customer_account=ACME&list_id=1&number=0472000000
```

**Response `200`**

```json
{
  "destination1": "810",
  "destination2": "811",
  "destination3": null,
  "destination4": null,
  "fallback": false
}
```

`fallback` is `true` when the caller's zone is not covered by the list: the four values are then the list's **fallback destinations**. If all four values are empty, the API answers `404 No destination found matching given parameters.` An unknown list returns `404 No list found matching given parameters.`

## CTI lookup

### Token URL

Copy the **Lookup URL** from the CTI page and append the calling number. No other authentication is needed:

`GET /api/smart-routings/ctis/t/{cti-token}/{origin}`

```json
{
  "id": 42,
  "origin": "0033612345678",
  "destination": "https://erp.example.com/customers/1234"
}
```

The origin must match exactly. If there is no match, the API answers `404`.

### Authenticated lookup

With a Bearer token (`cfd` or `client` scope), call `GET /api/smart-routings/ctis/lookup` with:

| Parameter | Required | Description |
|---|---|---|
| `customer_account` or `customer_id` | Yes | Your account |
| `cti_id`, `cti_name` or `cti_token` | Yes, one of them | The CTI to query |
| `origin` | Yes | The calling number, matched exactly |

**Example**

```
GET /api/smart-routings/ctis/lookup?customer_account=ACME&cti_name=VIP%20callers&origin=0033612345678
```

**Response `200`**

```json
{
  "id": 42,
  "cti_id": 4,
  "origin": "0033612345678",
  "destination": "https://erp.example.com/customers/1234",
  "created_at": "2024-03-04T10:15:00.000000Z",
  "updated_at": "2024-03-04T10:15:00.000000Z"
}
```

Without a match, the API answers `404` with `No customer found matching given parameters.`, `No CTI found matching given parameters.` or `No destination found matching given parameters.`

## Surveys

Call flows can also record the answers of a post-call survey with `POST /api/smart-routings/survey-records`, using the same token. The answers are listed in **Routings** > **Surveys**. See [CX-Engine API › Smart Routings](/en/docs/cx-api/smart-routings) for the payload.
