# Click-to-Call API — Reference

Reference for third-party developers and LLM coding assistants integrating with the **Click-to-Call** action on the IVR API endpoint (`ivrFilesApi.php`).

For the full HTML reference (with diagrams and Hebrew explanations) see [click2callApiDocs.html](click2callApiDocs.html).

---

## Base URL

```
https://app.ipsales.co.il/ivrFilesApi.php
```

The Click-to-Call feature is invoked by sending `action=click2call` to this endpoint.

---

## Authentication

Every request must include an API key.

| Location              | Example                              |
|-----------------------|--------------------------------------|
| Query string          | `?apiKey=YOUR_API_KEY`               |
| POST body (JSON)      | `{ "apiKey": "YOUR_API_KEY", ... }`  |
| POST form-urlencoded  | `apiKey=YOUR_API_KEY&...`            |

The API key identifies the tenant account that owns the extension. Treat it like a password — never embed in browser code or public repos.

---

## Overview

Click-to-Call connects an **agent's extension** to a **target phone number** in two stages:

1. The agent's extension rings first.
2. When the agent picks up, the PBX dials the target and bridges the two legs.

Use cases: a "Call now" button next to a contact in your CRM, dialing from a leads list, or quickly connecting two internal extensions.

The agent only enters the **internal extension number** they know (e.g. `101`). The system maps this to the actual SIP user behind the scenes — the agent never has to know the technical username.

---

## Action — `click2call`

### Request

| Param        | Required  | Type    | Description                                                                                                            |
|--------------|-----------|---------|------------------------------------------------------------------------------------------------------------------------|
| `action`     | yes       | string  | Must be `click2call`                                                                                                   |
| `apiKey`     | yes       | string  | Tenant API key                                                                                                         |
| `extension`  | yes       | string  | Internal extension number of the agent (e.g. `101`). Must belong to the tenant that owns the API key.                  |
| `target`     | yes       | string  | Number to dial. See [Target formats](#target-formats).                                                                 |
| `targetName` | no        | string  | Display name shown on the agent's phone screen (e.g. customer name from CRM). Falls back to the target number if omitted. |
| `ringSec`    | no        | integer | Seconds to ring the agent extension before giving up. Default `30`. Range `5–120`.                                     |

### Target formats

The `target` parameter accepts three kinds of numbers — auto-detected:

| Kind                          | Pattern              | Examples                                |
|-------------------------------|----------------------|-----------------------------------------|
| Israeli phone number          | Valid IL number      | `0501234567`, `+972501234567`, `00972501234567` |
| Internal extension (3 digits) | `^[1-9][0-9]{2}$`    | `101`, `205`, `999`                     |
| Extension display number      | `^099088\d+$`        | `0990880101`, `0990880205`              |

Non-Israeli phone numbers are rejected with `errorCode: 3`. Israeli numbers are normalized server-side to local format (`05XXXXXXXX`).

### Example — GET

```
https://app.ipsales.co.il/ivrFilesApi.php?action=click2call&apiKey=YOUR_API_KEY&extension=101&target=0501234567&targetName=%D7%99%D7%95%D7%A1%D7%A3
```

### Example — POST (JSON)

```bash
curl -X POST https://app.ipsales.co.il/ivrFilesApi.php \
  -H "Content-Type: application/json" \
  -d '{
    "action":     "click2call",
    "apiKey":     "YOUR_API_KEY",
    "extension":  "101",
    "target":     "0501234567",
    "targetName": "Customer Name",
    "ringSec":    30
  }'
```

### Successful response

HTTP 200, JSON:

```json
{
  "status":     "OK",
  "errorCode":  0,
  "callId":     "a1b2c3d4-...",
  "extension":  "101",
  "target":     "0501234567",
  "targetName": "Customer Name"
}
```

| Field        | Description                                                                                  |
|--------------|----------------------------------------------------------------------------------------------|
| `status`     | `"OK"` on success                                                                            |
| `errorCode`  | `0` on success                                                                               |
| `callId`     | Unique call identifier — store it in your CRM to link with recordings/activity records later |
| `extension`  | Echo of the agent extension                                                                  |
| `target`     | Normalized target number                                                                     |
| `targetName` | Echo of the display name (or empty string if not sent)                                       |

### Error response

HTTP 200, JSON (logical errors return `200` with `status: "ERROR"` — do not rely on HTTP status alone):

```json
{
  "status":    "ERROR",
  "errorCode": 4,
  "note":      "שלוחה לא נמצאה או לא שייכת לחשבון"
}
```

---

## Error codes

| `errorCode`              | Reason                                                          | Resolution                                                            |
|--------------------------|-----------------------------------------------------------------|-----------------------------------------------------------------------|
| `1`                      | `extension` parameter missing                                   | Add the agent extension to the request                                |
| `2`                      | `target` parameter missing                                      | Add the target number to the request                                  |
| `3`                      | `target` is not a valid Israeli number / extension / 099088 form | See [Target formats](#target-formats)                                |
| `4`                      | Extension not found, or not owned by the API key's tenant       | Verify the extension exists for this account                          |
| `6`                      | PBX unavailable / timeout                                        | Transient — retry; if persistent, contact support                     |
| `400` / `401` / `402` / `404` | PBX-side error (missing internal field, internal token, extension missing on PBX, internal failure) | Usually transient. If persistent, contact support with `callId` and timestamp |

---

## Implementation notes

- **Always check `status === "OK"`** — never rely on HTTP 200 alone, since logical errors are returned with HTTP 200 + `status: "ERROR"`.
- **Persist `callId`** when the call succeeds — it is the link to the recording and call detail record.
- **Display name** (`targetName`) is shown to the agent on their phone screen as soon as their extension rings, so they know who they're about to be connected to.
- **Number normalization** — Israeli targets are converted to local `05XXXXXXXX` format before dialing. The normalized form is echoed back in the response.
