---
title: "Add click-to-call to your CRM"
description: "Connect a CRM action to an existing A1PBX extension."
---

## Map the CRM user to an extension

Maintain a server-side mapping between the authenticated CRM user and their authorized A1PBX extension. Do not let the browser choose arbitrary source extensions or caller identities.

## Place the request on your server

On an explicit click, validate the destination and call [Originate](/docs/a1pbx/originate). Keep the A1PBX API key on the server. Return only the information your CRM needs.

### cURL

```bash
curl --fail-with-body --get \
  "https://$A1PBX_ACCOUNT_ID.a1routes.com/app/api/7/originate" \
  --header "Authorization: Basic $A1PBX_API_KEY" \
  --data-urlencode "extension=$EXTENSION" \
  --data-urlencode "destination=$DESTINATION"
```

### Node.js

```javascript
const url = new URL(`https://${process.env.A1PBX_ACCOUNT_ID}.a1routes.com/app/api/7/originate`);
url.searchParams.set('extension', process.env.EXTENSION);
url.searchParams.set('destination', process.env.DESTINATION);
const response = await fetch(url, {
  headers: {
    Authorization: `Basic ${process.env.A1PBX_API_KEY}`,
  },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.text());
```

### Python

```python
import os
import requests
url = f"https://{os.environ['A1PBX_ACCOUNT_ID']}.a1routes.com/app/api/7/originate"
response = requests.get(
    url,
    params={
        "extension": os.environ["EXTENSION"],
        "destination": os.environ["DESTINATION"],
    },
    headers={"Authorization": "Basic " + os.environ["A1PBX_API_KEY"]},
    timeout=30,
)
response.raise_for_status()
print(response.text)
```

### PHP

```php
<?php
$url = 'https://' . getenv('A1PBX_ACCOUNT_ID') . '.a1routes.com/app/api/7/originate';
$url .= '?' . http_build_query([
    'extension' => getenv('EXTENSION'),
    'destination' => getenv('DESTINATION'),
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => ['Authorization: Basic ' . getenv('A1PBX_API_KEY')],
]);
$body = curl_exec($ch);
if ($body === false) throw new RuntimeException(curl_error($ch));
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 400) throw new RuntimeException('HTTP ' . $status);
echo $body;
```

## Prevent duplicate calls

Disable the call action while a request is in flight. A timeout can leave the call outcome unknown, so do not retry automatically. Verify the result before offering another attempt. No idempotency guarantee is asserted by this reference.

## Test deliberately

Use an approved test extension and destination. Confirm caller identity, routing, response behavior, and the user experience before enabling this for a team.
