---
title: API overview
description: Base URL, conventions, and what the REST surface covers.
---

The REST API lives at:

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

Everything is JSON over HTTPS. Send `Content-Type: application/json`
on any request with a body.

## What it covers

| Resource | What it is for |
|---|---|
| [Subscribe](/api/subscribe) | Taking a signup from your own form |
| [Contacts](/api/contacts) | Reading and importing your audience |
| [Topics](/api/topics) | The things people consent to receive |
| [Lists](/api/lists) | Your own segmentation |
| [Suppressions](/api/suppressions) | Addresses you never want mailed |

Campaigns are built and sent from the dashboard. They involve a visual
editor and a review step that do not reduce well to an API call, and
sending one by accident from a script is not a mistake we want to make
easy.

## Conventions

**Ids are prefixed strings.** `ct_` for a contact, `tp_` for a topic,
`ls_` for a list. The prefix means an id that turns up in a log is
self-describing and a value passed to the wrong parameter is obvious.
Treat them as opaque.

**Field names are `snake_case`.** `first_name`, not `firstName`.

**Timestamps are ISO 8601, UTC.** `2026-03-14T09:30:00.000Z`.

**Single resources are wrapped in `data`:**

```json
{ "data": { "id": "ct_8vq2", "email": "ada@example.com" } }
```

**Collections carry `meta`:**

```json
{
  "data": [ { "id": "ct_8vq2" } ],
  "meta": { "limit": 20, "has_more": true, "next_cursor": "Y3RfOHZxMg" }
}
```

The envelope is consistent so a client can unwrap without knowing
which endpoint it called.

## Checking a key

```bash
curl https://api.zevcampaign.com/v1/ping \
  -H "Authorization: Bearer sk_test_your_key_here"
```

```json
{
  "data": {
    "ok": true,
    "environment": "test",
    "key_type": "secret"
  }
}
```

Useful in a deploy check: it confirms the key works and tells you
which environment you are pointed at, which is the thing people get
wrong.

## Stability

This is the supported, public interface, and it is the only one to
build against. It is versioned in the path and only ever added to:
new fields and new endpoints appear, existing ones do not change
shape or disappear underneath you.