
# API Access

An API (Application Programming Interface) is a way for different software systems to talk to each other. The <span data-t="appName">DM Champ</span> API lets you (or your developer) automatically create contacts, send messages, manage lists, and receive incoming messages from custom channels — all without using the dashboard.

::: walkthrough api-access
:::

**Why use the API?** If you want to connect the app to a tool that doesn't have a built-in integration, or you need to automate repetitive tasks at scale, the API is the way to do it.

::: note
**Note:** This page is more technical in nature. If you are a business owner and not a developer, you may want to share this page with your technical team or a freelance developer.
:::


---

## Generating Your API Key

::: note
**Note:** API access is a paid feature available on qualifying plans. If your plan doesn't include it, API requests will be rejected with a `403` response. Check your plan or contact support if you're unsure whether API access is enabled.
:::


1. In the left sidebar, click **Settings** (gear icon).
2. In the Settings sidebar, under the **Integrations** group, click **API Key**.

::: master-only
<figure><img src="../.gitbook/assets/v2-settings-overview.png" alt="The Settings page, showing the grouped left-rail navigation"><figcaption><p>API Key sits under the Integrations group in Settings, next to Webhooks and Booking & Calendar.</p></figcaption></figure>
:::

3. If you don't have a key yet, click **Generate API key**.
4. If you already have one, it's shown masked under **Your key**. If your key supports it, click **Show** to reveal it, then **Copy** to copy it — you'll see a confirmation toast.
5. Store the key somewhere safe — you'll need it for every API request.

::: master-only
<figure><img src="../.gitbook/assets/v2-api-access-key-section.png" alt="The API Key settings section, showing a masked key and the Regenerate card"><figcaption><p>Your key is shown masked. Older keys may show "Your key can't be displayed" instead of Show/Copy — the key still works, you just can't view the plaintext again without regenerating. The Regenerate card is further down the same section, not a separate page.</p></figcaption></figure>
:::

::: note
**Note:** Some accounts see "Your key can't be displayed" instead of a Show/Copy control — this happens for keys created before the app could re-display them. The key still works normally; you only need **Regenerate** (below the key card, in the same section) if you actually need to see the plaintext again. Regenerating invalidates the old key immediately and breaks every integration using it until you paste in the new one — update your integrations right after.
:::


::: warning
**Important:** Your API key is like a password — it grants full access to your account. Do not share it publicly or post it anywhere others can see it. If you believe your key has been compromised, regenerate it immediately.
:::


> **Team members:** the API key belongs to the account owner, so if you're signed in as an invited team member (including an Admin) the section shows a note instead of the key. Sign in as the account owner to view, copy or regenerate it — that applies to scoped keys too.

> **Where to find it:** **API Key** is its own section under Settings → Integrations, separate from **Webhooks**. If a guide or a colleague tells you to look under "Webhooks" for the key, look one section over instead.

---

## Base URL

All API requests use the following base web address:

```
https://api.dmchamp.com/v1/
```

---

## Authentication

Every request must include your API key so the platform knows it's you. The simplest way is to add it to the end of the web address:

```
https://api.dmchamp.com/v1/contacts?apiKey=YOUR_API_KEY
```

You can also send the key as a request header instead of in the URL (recommended for production, so the key doesn't end up in server logs):

```
X-API-Key: YOUR_API_KEY
```
```
Authorization: Bearer YOUR_API_KEY
```

All requests must use a secure connection (HTTPS). Insecure (HTTP) requests are rejected.

> **Looking for the full developer guides?** This page is a quick intro covering the most common operations. For complete, step-by-step guides — every resource, with cURL, JavaScript, and Python examples — see [Getting Started with the API](../api/getting-started.md) and the [API Reference](../api/reference.md).

---

## Common API Operations

### Create a Contact

**Request:**

```http
POST https://api.dmchamp.com/v1/contacts?apiKey=YOUR_API_KEY
Content-Type: application/json

{
  "firstName": "Jane",
  "lastName": "Smith",
  "phoneNumber": "+15551234567",
  "email": "jane@example.com"
}
```

**Required fields:** a `phoneNumber` (with country code) is always required to create a contact. An email address alone is not enough — a request without a valid phone number is rejected. The email is optional.

**Response:**

```json
{
  "success": true,
  "data": {
    "message": "Successfully created new contact",
    "contactId": "abc123xyz",
    "listsAdded": []
  }
}
```

Save `data.contactId` — you'll need it for the "Add a Contact to a List" call.

::: note
**Note:** if a contact with the same phone number already exists, the API does **not** create or return that contact — it returns `{ "success": false, "error_code": 409 }`. Look the existing contact up first with `GET https://api.dmchamp.com/v1/contacts?phoneNumber=...`.
:::


---

### Add a Contact to a List

```http
POST https://api.dmchamp.com/v1/contacts/lists?apiKey=YOUR_API_KEY
Content-Type: application/json

{
  "contactId": "abc123xyz",
  "listId": "YOUR_LIST_ID"
}
```

Find a list's ID in the app under **Contacts → Lists**, from a list's row menu (**Copy list ID**).

---

### Update a Contact

```http
PUT https://api.dmchamp.com/v1/contacts/YOUR_CONTACT_ID?apiKey=YOUR_API_KEY
Content-Type: application/json

{
  "customFields": { "company": "Acme Inc" }
}
```

Only the fields you include are changed. This is also the way to bulk-load custom field values after an import — see [Custom Fields, Lead Profile & Notes](../get-started/custom-contact-fields.md#bulk-loading-custom-fields). Full details in the [Contacts API](../api/contacts.md).

---

### Send a Message (Custom Channel)

```http
POST https://api.dmchamp.com/v1/send_custom_channel_message?apiKey=YOUR_API_KEY
Content-Type: application/json

{
  "customData": {
    "fromId": "external-contact-id",
    "customChannel": "my-channel",
    "body": "Hello Jane! Your order has been shipped.",
    "campaignId": "optional-campaign-id",
    "firstName": "Jane",
    "lastName": "Smith"
  }
}
```

| Field | Required | Description |
|---|---|---|
| `customData.fromId` | Yes | The contact's ID on your platform |
| `customData.customChannel` | Yes | The name of your custom channel |
| `customData.body` | Yes | The message text to send |
| `customData.campaignId` | No | Route the message to a specific campaign |
| `customData.firstName` | No | Contact's first name (used when creating a new contact) |
| `customData.lastName` | No | Contact's last name |
| `customData.email` | No | Contact's email address |

::: note
**Note:** this endpoint is for custom channel messaging. For WhatsApp, SMS, Instagram, and Messenger, messages go out through Broadcasts, Campaigns, and AI Agents.
:::


---

### Receive Incoming Messages (Custom Channel)

Accept messages from external systems as a custom channel. This is how integrations like GoHighLevel send messages into <span data-t="appName">DM Champ</span>. See [Custom Channels](../messaging-channels/custom-channels.md) for full details.

```http
POST https://api.dmchamp.com/v1/incoming_custom_channel_message?apiKey=YOUR_API_KEY
Content-Type: application/json

{
  "customData": {
    "messageSid": "unique-message-id",
    "fromId": "external-contact-id",
    "toId": "your-user-id",
    "body": "Customer's message here",
    "channel": "custom",
    "status": "received"
  },
  "messageType": "text"
}
```

| Field | Required | Description |
|---|---|---|
| `customData.messageSid` | Yes | A unique ID for this message (prevents duplicates). You can also use `customData.id`. |
| `customData.fromId` | Yes | The sender's ID in your external system. |
| `customData.toId` | Yes | Your business identifier. |
| `customData.body` | Yes | The message text. |
| `customData.channel` | No | A label for the source (e.g., `"email"`, `"livechat"`, `"custom"`). |
| `customData.status` | No | Message status. Defaults to `"received"`. |
| `messageType` | No | `"text"` for text messages, `"reaction"` for emoji reactions. |

---

## Available Operations Overview

| Action | Method | Address | Description |
|---|---|---|---|
| Create a contact | `POST` | `/contacts` | Add a new contact to your account |
| Get contact details | `GET` | `/contacts?phoneNumber=X` or `/contacts?email=X` | Look up a contact by phone number or email |
| Update a contact | `PUT` | `/contacts/{contactId}` | Update any field on an existing contact |
| Add contact to list | `POST` | `/contacts/lists` | Add an existing contact to a specific list |
| Send a message | `POST` | `/send_custom_channel_message` | Send a message through a custom channel |
| Receive a message | `POST` | `/incoming_custom_channel_message` | Accept a message from an external system |

---

## Rate Limiting

The API enforces rate limits to ensure platform stability. Exceeding your limit returns `429 Too Many Requests` — back off and retry after the time indicated in the response headers. For high-volume use cases (bulk imports), use the built-in [import feature](../get-started/importing-contacts.md) or email [<span data-t="supportEmail">hi@dmchamp.com</span>](mailto:hi@dmchamp.com) for guidance.

---

## Best Practices

- **Store your API key securely** — a password manager or server-side configuration, never client-side code a browser visitor could read.
- **Always include the country code** in phone numbers (`+1` for US, `+44` for UK, `+31` for Netherlands).
- **Handle errors gracefully** — check status codes and read any error messages returned.
- **Handle duplicates** — a duplicate phone number returns `{ "success": false, "error_code": 409 }` instead of a new contact. Look the contact up first if you need to work with it.
- **Test with a small dataset** before running bulk operations.

---

## Error Responses

```json
{
  "error": {
    "code": "INVALID_PHONE",
    "message": "Phone number must include a valid country code."
  }
}
```

| Status Code | Meaning |
|---|---|
| `200` | Success |
| `201` | Resource created |
| `400` | Bad request — check your parameters |
| `401` | Unauthorized — invalid or missing API key |
| `403` | Forbidden — your plan doesn't include API access, or you lack permission |
| `404` | Resource not found |
| `429` | Rate limit exceeded |
| `500` | Server error — email [<span data-t="supportEmail">hi@dmchamp.com</span>](mailto:hi@dmchamp.com) if this persists |

---

## Next Steps

- [Webhooks](webhooks.md) — receive real-time notifications from the app (a separate section from your API key).
- [Connect AI Assistants (MCP)](connect-ai-clients.md) — use the same API key to let Claude drive your account.
- [Facebook Lead Forms](facebook-lead-forms.md) — use the API with automation platforms to capture leads.
- [GoHighLevel Integration](ghl-integration.md) — a full two-way API integration example.
