# Calling

> Verify your own number, list the numbers you can call from, add Fondaro numbers, read prices and switch calling on or off.

The calling API manages the numbers your team calls from: each person's own mobile, verified once, and Fondaro numbers the agency adds per country. Calls are placed by the person's own browser or phone app; Ask Fondaro never places a call. The paths keep their historical `/twilio` prefix.

These endpoints take a signed-in member's session token (`Authorization: Bearer <session-token>`); API keys do not open them. See [Authentication](https://www.fondaro.com/docs/api/authentication.md).

Every member manages their own number. Adding, assigning and releasing Fondaro numbers, country requirements and the on/off switch are for organization admins; a member gets `403`.

## Your own number

### Start verifying your number

`POST /twilio/phone-numbers/verify-caller-id`

Fondaro calls the number and the person types the six-digit `validationCode` on their phone.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `phoneNumber` | Body, string | Yes | The number in E.164 form, for example `+34612345678` |

```bash
curl -X POST https://api.fondaro.com/twilio/phone-numbers/verify-caller-id \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "phoneNumber": "+34612345678" }'
```

```json
{
  "id": "5b0c1e2a-...",
  "phoneNumber": "+34612345678",
  "status": "pending",
  "validationCode": "482913",
  "expiresAt": "2026-10-02T10:24:03.000Z",
  "createdAt": "2026-10-02T10:14:03.000Z",
  "updatedAt": "2026-10-02T10:14:03.000Z"
}
```

When the first own number in an organization is verified, calling is set up and switched on for the organization, unless it already has a Fondaro number. Calling for an organization without a plan is refused.

### Follow a verification

| Endpoint | Purpose |
|---|---|
| `GET /twilio/phone-numbers/caller-id-verifications/current` | Your latest attempt |
| `GET /twilio/phone-numbers/caller-id-verifications/:attemptId` | One attempt; poll it while `status` is `pending` |
| `DELETE /twilio/phone-numbers/caller-id-verifications/:attemptId` | Cancel a pending attempt |
| `POST /twilio/phone-numbers/confirm-caller-id` | Check the attempt now and save the number if the call succeeded. Body `{ "phoneNumber" }` |

`status` ends as `succeeded`, `failed`, `expired` or `cancelled`. A failed attempt carries `failureReason`: `verification_failed`, `provider_unavailable` or `conflict`.

```bash
curl https://api.fondaro.com/twilio/phone-numbers/caller-id-verifications/5b0c1e2a-... \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

```json
{ "id": "5b0c1e2a-...", "phoneNumber": "+34612345678", "status": "succeeded", "validationCode": null }
```

### Read your number

`GET /twilio/phone-numbers/my-caller-id`

Returns your verified number, or `{ "verified": false }` when you have none.

```bash
curl https://api.fondaro.com/twilio/phone-numbers/my-caller-id \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

```json
{
  "id": "e81d...",
  "phoneNumber": "+34612345678",
  "numberType": "verified_caller_id",
  "assignmentType": "assigned",
  "assignedUserIds": ["user_2abc..."]
}
```

### Remove your number

`DELETE /twilio/phone-numbers/caller-id/:id`

Removes a verified number. A member can remove their own; an admin can remove any.

```bash
curl -X DELETE https://api.fondaro.com/twilio/phone-numbers/caller-id/e81d... \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

```json
{ "removed": true }
```

## List the numbers you can call from

`GET /twilio/phone-numbers`

| Parameter | Type | Required | Description |
|---|---|---|---|
| `scope` | Query, `mine` or `org` | No | `mine`: shared numbers and numbers assigned to you. `org` (default): every number, admins only; a member always gets `mine` |

```bash
curl "https://api.fondaro.com/twilio/phone-numbers?scope=mine" \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

```json
{
  "numbers": [
    {
      "id": "e81d...",
      "ownerUserId": "user_2abc...",
      "phoneNumber": "+34612345678",
      "numberType": "verified_caller_id",
      "assignmentType": "assigned",
      "assignedUserIds": ["user_2abc..."],
      "isPrimary": false,
      "countryCode": "ES"
    }
  ],
  "myCallerIdNumber": "+34612345678",
  "callingBlockedCode": null
}
```

`numberType` is `purchased` (a Fondaro number) or `verified_caller_id` (someone's own number). `callingBlockedCode` is `null` when you can call, otherwise `NO_ROUTING_NUMBER` or `NO_CALLER_ID` (see [Why a person cannot call](#why-a-person-cannot-call)).

## Fondaro numbers

### Countries and available numbers

| Endpoint | Purpose |
|---|---|
| `GET /twilio/phone-numbers/countries` | Countries with `{ code, name, numberTypes }` |
| `GET /twilio/phone-numbers/search` | Admins: numbers available to buy |

`search` takes `country` (ISO 3166-1 alpha-2, required), `numberType` (`local` by default), `pageSize` (1 to 50, default 20), `pageToken`, `contains`, `areaCode`, `locality` and `region`.

```bash
curl "https://api.fondaro.com/twilio/phone-numbers/search?country=ES&numberType=local&pageSize=5" \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

```json
{
  "numbers": [
    { "phoneNumber": "+34910000000", "friendlyName": "+34 910 00 00 00", "locality": "Madrid", "region": "MD", "isoCountry": "ES" }
  ],
  "nextPageToken": null
}
```

### Add a number

`POST /twilio/phone-numbers/purchase`

Admins only. Buys a number for the organization. Countries that ask for business details need an approved request first (see [Country requirements](#country-requirements)).

The organization needs an active plan or trial with a card on file: without a plan the answer is `403`, and without a card or with an unpaid balance it is `402`. An organization holds at most 50 numbers; past that the answer is `409` with the code `TWILIO_NUMBER_LIMIT_REACHED`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `countryCode` | Body, string | Yes | ISO 3166-1 alpha-2 |
| `numberType` | Body, `local`, `mobile`, `tollFree` or `national` | No | Default `local` |
| `specificNumber` | Body, string | No | An E.164 number from `search`; otherwise the first available |
| `bundleSid` | Body, string | No | The approved country request to buy under |
| `friendlyName` | Body, string | No | A label |

```bash
curl -X POST https://api.fondaro.com/twilio/phone-numbers/purchase \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "countryCode": "ES", "specificNumber": "+34910000000", "friendlyName": "Madrid office" }'
```

```json
{ "id": "a12f...", "phoneNumber": "+34910000000", "numberType": "purchased", "assignmentType": "shared", "countryCode": "ES" }
```

### Assign a number

`PATCH /twilio/phone-numbers/:id`

Admins only.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `friendlyName` | Body, string | No | A label |
| `assignmentType` | Body, `shared` or `assigned` | No | `shared`: everyone may call from it. `assigned`: only the people below |
| `assignedUserIds` | Body, string[] | No | User ids |
| `teamIds` | Body, UUID[] | No | Teams, expanded to their current members; see [Teams](https://www.fondaro.com/docs/api/teams.md) |

```bash
curl -X PATCH https://api.fondaro.com/twilio/phone-numbers/a12f... \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "assignmentType": "assigned", "assignedUserIds": ["user_2abc..."] }'
```

```json
{ "id": "a12f...", "assignmentType": "assigned", "assignedUserIds": ["user_2abc..."] }
```

### Release a number

`DELETE /twilio/phone-numbers/:id`

Admins only. The primary number cannot be released.

```bash
curl -X DELETE https://api.fondaro.com/twilio/phone-numbers/a12f... \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

```json
{ "released": true }
```

## Read prices

`GET /twilio/pricing`

Returns the monthly price of a Fondaro number and the per-minute call price in your billing currency.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `country` | Query, string | No | ISO 3166-1 alpha-2. Defaults to your organization's country |
| `numberType` | Query, string | No | Default `local` |

```bash
curl "https://api.fondaro.com/twilio/pricing?country=ES" \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

```json
{
  "numberRentalCustomerPrice": 1.5,
  "perMinuteCustomerPrice": 0.0195,
  "country": "ES",
  "currency": "EUR"
}
```

`numberRentalCustomerPrice` is the monthly price of a number and `perMinuteCustomerPrice` the price of a call minute, in `currency`. The rental price is `null` where numbers cannot be rented.

## Country requirements

Some countries ask for business details and documents before Fondaro can give you a number there. Admins only.

| Endpoint | Purpose |
|---|---|
| `GET /twilio/regulatory/regulations?country=DE&numberType=local&endUserType=business` | What the country asks for: `{ requiresBundle, regulations }` |
| `GET /twilio/regulatory/bundles` | Your requests, newest first |
| `GET /twilio/regulatory/bundles/:id` | One request |
| `POST /twilio/regulatory/bundles` | Start a request: `{ friendlyName, email, isoCountry, numberType, endUserType, regulationSid? }`. `numberType` is `local`, `mobile`, `toll-free` or `national`; `endUserType` is `business` or `individual` |
| `POST /twilio/regulatory/bundles/:id/end-user` | Add the business or person: `{ friendlyName, type, attributes }` |
| `POST /twilio/regulatory/bundles/:id/documents` | Upload a document: multipart `file` plus `friendlyName`, `type` and optional `attributes` |
| `POST /twilio/regulatory/bundles/:id/submit` | Send the request for review |
| `DELETE /twilio/regulatory/bundles/:id` | Delete a request. Returns `{ "deleted": true }` |

A request's `status` is `draft`, `pending-review`, `in-review`, `provisionally-approved`, `twilio-approved` or `twilio-rejected`.

### Send a request for review

`POST /twilio/regulatory/bundles/:id/submit`

A `draft` or a rejected request can be sent; anything else returns `400` "This has already been sent." When the details do not pass the check, the `400` names each field:

```bash
curl -X POST https://api.fondaro.com/twilio/regulatory/bundles/3c9d.../submit \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

```json
{
  "statusCode": 400,
  "code": "DOCUMENTS_NOT_COMPLIANT",
  "message": "Some details need a fix: The business address is missing",
  "fields": [
    { "field": "business_address", "requirement": "Business address", "reason": "The business address is missing" }
  ]
}
```

Each entry in `fields` has `field`, `requirement` and `reason`, any of which may be `null`. Once a request is approved, an admin adds the number with `POST /twilio/phone-numbers/purchase`.

## Switch calling on or off

`POST /twilio/setup/enable` and `POST /twilio/setup/disable`

Admins only. Turning calling off stops every member calling until an admin turns it on again; Fondaro does not turn it back on.

```bash
curl -X POST https://api.fondaro.com/twilio/setup/disable \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

```json
{ "callingEnabled": false }
```

## Why a person cannot call

`GET /twilio/token` returns `{ "token": "..." }`, the short-lived token the dialer in the browser or phone app uses to place a call. When the person cannot call it returns `400` with a stable `code`:

| `code` | `message` |
|---|---|
| `CALLING_DISABLED` | Calling is switched off for your agency. |
| `CALLING_PAUSED_BY_FONDARO` | Calling is paused while we check unusual activity. It comes back on its own. |
| `NO_ROUTING_NUMBER` | Calling isn't ready yet. |
| `NO_CALLER_ID` | Add your phone number to start calling. |

```json
{ "statusCode": 400, "code": "NO_CALLER_ID", "message": "Add your phone number to start calling." }
```

## Errors

| Status | When |
|---|---|
| `400` | Validation failed, a verification expired, a request was already sent, or the primary number was released |
| `401` | No valid session token |
| `403` | A member called an admin-only endpoint, or the organization has no plan for calling |
| `404` | The number, attempt or request does not exist in your organization |
| `409` | The number is already used in your organization, or another verification for it is in progress |
| `422` | `CALLER_ID_COUNTRY_NOT_SUPPORTED`: Fondaro cannot call numbers in that country yet |
| `503` | The phone service is unavailable; try again |

Source: https://www.fondaro.com/docs/api/calling
