---
sidebar_position: 13
title: Push Credentials
description: Create and manage APNs and FCM push notification credentials for partner mobile applications to receive VoIP incoming call pushes via the Firetell REST API.
---

# Push Credentials

Configure push notification credentials for your custom mobile applications to receive VoIP push notifications when incoming calls arrive. Each credential is tied to an API Key SID and enables Firetell to dispatch push notifications using **your own** APNs (iOS) or FCM (Android) credentials instead of Firetell's built-in push infrastructure.

:::info
**When to Use Push Credentials**

Push credentials are required when you build **your own mobile app** (not the Firetell Agent app) and want to receive incoming call pushes. If your agents use the official Firetell Agent app, push credentials are already configured — you do not need to set up anything here.
:::

## Endpoints

| Method   | Endpoint                | Description                  |
| -------- | ----------------------- | ---------------------------- |
| `GET`    | `/push-credentials`     | List all push credentials    |
| `GET`    | `/push-credentials/:id` | Get push credential details  |
| `POST`   | `/push-credentials`     | Create a new push credential |
| `PATCH`  | `/push-credentials/:id` | Update a push credential     |
| `DELETE` | `/push-credentials/:id` | Delete a push credential     |

## The Push Credential Object

| Field                           | Type    | Description                                                                                |
| ------------------------------- | ------- | ------------------------------------------------------------------------------------------ |
| `id`                            | string  | Unique identifier (prefixed with `pc_`)                                                    |
| `workspace_id`                  | string  | Workspace identifier                                                                       |
| `api_key_sid`                   | string  | The API Key SID that this credential is associated with                                    |
| `name`                          | string  | Display name for this credential                                                           |
| `platform`                      | string  | Platform: `ios` or `android`                                                               |
| `enabled`                       | boolean | Whether this credential is active                                                          |
| `apns_key_id`                   | string  | _(iOS only)_ 10-character Key ID from Apple Developer portal                               |
| `apns_team_id`                  | string  | _(iOS only)_ 10-character Team ID from Apple Developer portal                              |
| `apns_private_key_encrypted`    | string  | _(iOS only)_ Always `"******"` in responses — the private key is encrypted at rest         |
| `apns_bundle_id`                | string  | _(iOS only)_ iOS app bundle identifier (e.g., `com.yourcompany.app`)                       |
| `apns_environment`              | string  | _(iOS only)_ `sandbox` or `production`                                                     |
| `fcm_service_account_encrypted` | string  | _(Android only)_ Always `"******"` in responses — the service account is encrypted at rest |
| `fcm_package_name`              | string  | _(Android only)_ Android app package name                                                  |
| `created_at`                    | string  | ISO 8601 creation timestamp                                                                |
| `updated_at`                    | string  | ISO 8601 last update timestamp                                                             |

:::caution
**Credential Security**

Sensitive fields (`apns_private_key`, `fcm_service_account`) are **encrypted at rest** using AES-256-GCM and are **never returned** in API responses. You will see `"******"` as a placeholder. If you lose your credentials, you must re-upload new ones.
:::

---

## Quota

Each workspace can have a maximum of **30 push credentials**. If you need more, contact [enterprise@firetell.com](mailto:enterprise@firetell.com).

---

## List Push Credentials

```
GET /push-credentials
```

Retrieve a paginated list of all push credentials in the workspace.

### Authentication

Requires `ApiKey` or JWT with any role.

### Query Parameters

| Parameter | Type   | Default | Description                       |
| --------- | ------ | ------- | --------------------------------- |
| `page`    | number | `1`     | Page number (min: 1)              |
| `limit`   | number | `20`    | Items per page (min: 1, max: 100) |

### Request

```bash
curl -X GET "https://{workspace_id}.firetell.app/api/v1/push-credentials?page=1&limit=10" \
  -H "Authorization: ApiKey sk-YOUR_API_KEY"
```

### Response

```json
{
  "data": [
    {
      "id": "pc_a1b2c3d4e5f6g7h8",
      "workspace_id": "ws_123456789",
      "api_key_sid": "sid-650000000000000000000001",
      "name": "Production iOS App",
      "platform": "ios",
      "enabled": true,
      "apns_key_id": "ABC123DEFG",
      "apns_team_id": "TEAM123456",
      "apns_private_key_encrypted": "******",
      "apns_bundle_id": "com.yourcompany.app",
      "apns_environment": "production",
      "created_at": "2026-08-01T10:00:00.000Z",
      "updated_at": "2026-08-01T10:00:00.000Z"
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "limit": 20,
    "total_pages": 1
  }
}
```

---

## Get Push Credential

```
GET /push-credentials/:id
```

Retrieve the details of a specific push credential.

### Authentication

Requires `ApiKey` or JWT with any role.

### Request

```bash
curl -X GET "https://{workspace_id}.firetell.app/api/v1/push-credentials/pc_a1b2c3d4e5f6g7h8" \
  -H "Authorization: ApiKey sk-YOUR_API_KEY"
```

### Response

```json
{
  "id": "pc_a1b2c3d4e5f6g7h8",
  "workspace_id": "ws_123456789",
  "api_key_sid": "sid-650000000000000000000001",
  "name": "Production iOS App",
  "platform": "ios",
  "enabled": true,
  "apns_key_id": "ABC123DEFG",
  "apns_team_id": "TEAM123456",
  "apns_private_key_encrypted": "******",
  "apns_bundle_id": "com.yourcompany.app",
  "apns_environment": "production",
  "created_at": "2026-08-01T10:00:00.000Z",
  "updated_at": "2026-08-01T10:00:00.000Z"
}
```

---

## Create Push Credential

```
POST /push-credentials
```

Create a new push credential. The request body varies depending on the platform.

### Authentication

Requires `ApiKey` or JWT with role `owner` or `editor`.

### Request Body (iOS / APNs)

| Parameter          | Type   | Required | Description                                               |
| ------------------ | ------ | -------- | --------------------------------------------------------- |
| `name`             | string | **Yes**  | Display name (max 100 chars)                              |
| `api_key_sid`      | string | **Yes**  | API Key SID (`sid-...`) to associate this credential with |
| `platform`         | string | **Yes**  | Must be `ios`                                             |
| `apns_key_id`      | string | **Yes**  | 10-character Key ID from Apple Developer portal           |
| `apns_team_id`     | string | **Yes**  | 10-character Team ID from Apple Developer portal          |
| `apns_private_key` | string | **Yes**  | Full content of the `.p8` private key file (PEM format)   |
| `apns_bundle_id`   | string | **Yes**  | iOS app bundle identifier (e.g., `com.yourcompany.app`)   |
| `apns_environment` | string | No       | `sandbox` (default) or `production`                       |

### Request Example (iOS)

```bash
curl -X POST "https://{workspace_id}.firetell.app/api/v1/push-credentials" \
  -H "Authorization: ApiKey sk-YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production iOS App",
    "api_key_sid": "sid-650000000000000000000001",
    "platform": "ios",
    "apns_key_id": "ABC123DEFG",
    "apns_team_id": "TEAM123456",
    "apns_private_key": "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCC...\n-----END PRIVATE KEY-----",
    "apns_bundle_id": "com.yourcompany.app",
    "apns_environment": "production"
  }'
```

### Request Body (Android / FCM)

| Parameter             | Type   | Required | Description                                                           |
| --------------------- | ------ | -------- | --------------------------------------------------------------------- |
| `name`                | string | **Yes**  | Display name (max 100 chars)                                          |
| `api_key_sid`         | string | **Yes**  | API Key SID (`sid-...`) to associate this credential with             |
| `platform`            | string | **Yes**  | Must be `android`                                                     |
| `fcm_service_account` | string | **Yes**  | Firebase Service Account JSON (must have `"type": "service_account"`) |
| `fcm_package_name`    | string | No       | Android package name (e.g., `com.yourcompany.app`)                    |

### Request Example (Android)

```bash
curl -X POST "https://{workspace_id}.firetell.app/api/v1/push-credentials" \
  -H "Authorization: ApiKey sk-YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production Android App",
    "api_key_sid": "sid-650000000000000000000001",
    "platform": "android",
    "fcm_service_account": "{\"type\": \"service_account\", \"project_id\": \"my-project\", ...}",
    "fcm_package_name": "com.yourcompany.app"
  }'
```

### Response (`201 Created`)

```json
{
  "id": "pc_a1b2c3d4e5f6g7h8",
  "workspace_id": "ws_123456789",
  "api_key_sid": "sid-650000000000000000000001",
  "name": "Production iOS App",
  "platform": "ios",
  "enabled": true,
  "apns_key_id": "ABC123DEFG",
  "apns_team_id": "TEAM123456",
  "apns_private_key_encrypted": "******",
  "apns_bundle_id": "com.yourcompany.app",
  "apns_environment": "production",
  "created_at": "2026-08-01T10:00:00.000Z",
  "updated_at": "2026-08-01T10:00:00.000Z"
}
```

---

## Update Push Credential

```
PATCH /push-credentials/:id
```

Update an existing push credential. Only the fields you provide will be updated.

### Authentication

Requires `ApiKey` or JWT with role `owner` or `editor`.

### Request Body

| Parameter             | Type    | Description                                              |
| --------------------- | ------- | -------------------------------------------------------- |
| `name`                | string  | Updated display name                                     |
| `enabled`             | boolean | Enable or disable this credential                        |
| `apns_key_id`         | string  | _(iOS)_ Updated Key ID                                   |
| `apns_team_id`        | string  | _(iOS)_ Updated Team ID                                  |
| `apns_private_key`    | string  | _(iOS)_ New private key (replaces existing)              |
| `apns_bundle_id`      | string  | _(iOS)_ Updated bundle identifier                        |
| `apns_environment`    | string  | _(iOS)_ `sandbox` or `production`                        |
| `fcm_service_account` | string  | _(Android)_ New service account JSON (replaces existing) |
| `fcm_package_name`    | string  | _(Android)_ Updated package name                         |

:::tip
To rotate credentials, only send the `apns_private_key` or `fcm_service_account` field. Other fields remain unchanged.
:::

### Request

```bash
curl -X PATCH "https://{workspace_id}.firetell.app/api/v1/push-credentials/pc_a1b2c3d4e5f6g7h8" \
  -H "Authorization: ApiKey sk-YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated iOS App Name",
    "apns_environment": "production"
  }'
```

### Response

```json
{
  "id": "pc_a1b2c3d4e5f6g7h8",
  "workspace_id": "ws_123456789",
  "api_key_sid": "sid-650000000000000000000001",
  "name": "Updated iOS App Name",
  "platform": "ios",
  "enabled": true,
  "apns_key_id": "ABC123DEFG",
  "apns_team_id": "TEAM123456",
  "apns_private_key_encrypted": "******",
  "apns_bundle_id": "com.yourcompany.app",
  "apns_environment": "production",
  "created_at": "2026-08-01T10:00:00.000Z",
  "updated_at": "2026-08-05T14:30:00.000Z"
}
```

---

## Delete Push Credential

```
DELETE /push-credentials/:id
```

Permanently delete a push credential. Devices associated with the API Key SID will no longer receive VoIP push notifications.

### Authentication

Requires `ApiKey` or JWT with role `owner` or `editor`.

### Request

```bash
curl -X DELETE "https://{workspace_id}.firetell.app/api/v1/push-credentials/pc_a1b2c3d4e5f6g7h8" \
  -H "Authorization: ApiKey sk-YOUR_API_KEY"
```

### Response

```json
{
  "deleted": true
}
```

---

## Error Responses

### Quota Exceeded (`403`)

```json
{
  "statusCode": 403,
  "message": "Maximum 30 push credentials per workspace. Delete unused credentials first.",
  "error": "Forbidden"
}
```

### Invalid API Key SID (`400`)

```json
{
  "statusCode": 400,
  "message": "API Key with SID \"sid-invalid\" not found in this workspace.",
  "error": "Bad Request"
}
```

### Invalid FCM Service Account (`400`)

```json
{
  "statusCode": 400,
  "message": "fcm_service_account must be a valid Firebase Service Account JSON with \"type\": \"service_account\".",
  "error": "Bad Request"
}
```
