---
title: Building with an AI agent
description: Everything a model needs to integrate ZevCampaign, in the formats it reads best.
---

These docs are built to be read by machines as well as people. If you
are working with Claude, ChatGPT, Cursor, Copilot or anything similar,
start here rather than pasting screenshots.

## The three entry points

**`/llms.txt`** — a curated index of every page, following the
[llms.txt convention](https://llmstxt.org). Titles, one-line
descriptions, and a link to each page's raw markdown. Start here when
you want the model to find its own way around.

```
https://docs.zevcampaign.com/llms.txt
```

**`/llms-full.txt`** — every page concatenated into one file, with
page boundaries marked so the model can cite back to a source URL. Use
this when you would rather spend the tokens once and have the whole
product in context.

```
https://docs.zevcampaign.com/llms-full.txt
```

**`<any page>.md`** — append `.md` to any URL here and you get that
page's clean markdown, no navigation, no HTML.

```
https://docs.zevcampaign.com/api/subscribe.md
```

## Copy for AI

Every page has a **Copy for AI** button in its header. It copies the
page's markdown together with a short preamble that tells the model
what you are building and where to find the rest. Paste it as your
first message.

## A prompt that works

```text
I am integrating ZevCampaign, an email marketing platform, into my
<framework> app.

Read https://docs.zevcampaign.com/llms.txt first, then fetch the pages
you need.

I want to:
- post signups from my front-end form
- receive and verify webhooks on my server
- keep my own database in sync with unsubscribes

Use my language's standard HTTP client. Ask me before assuming
anything about my stack.
```

## Four things to tell your agent

Models reliably get these wrong on a first pass, because most email
APIs work differently. Worth stating them up front.

**Use a publishable key in the browser, a secret key on the server.**
Publishable keys can only reach `/v1/subscribe`. A model that reaches
for a secret key in front-end code has made a real security mistake,
not a style one.

**The subscribe response is deliberately vague.** It returns
`confirmation_sent` or `subscribed` and nothing else, on purpose. An
agent writing branching logic for "already subscribed" is writing code
for a case that will never arrive.

**Unsubscribes are one-way.** Re-importing an unsubscribed contact is
refused, not silently applied. Code that "syncs" a local list by
re-posting everybody will hit `contact_unsubscribed`, and that is
correct behaviour rather than an error to retry around.

**Verify webhook signatures.** An unverified endpoint accepts forged
events from anyone who learns the URL. The method is on
[verifying signatures](/webhooks/signatures), and it is five lines.

## Also worth loading

- [API reference](/api/) — every endpoint, with its fields and error
  codes
- [Event catalogue](/webhooks/events) — every webhook with its payload