DeployLog speaks HTTP and JSON. Integration requests go to /api/cli/* and authenticate with an API key on every call; without a valid key the answer is 401 and the message Valid API key required. The CLI is chapter 05, the GitHub Action chapter 06, and API keys chapter 11.
Limits
| What | Bound |
|---|---|
| Entry title | 1 to 200 characters |
| Entry body markdown | 1 to 50,000 characters |
| Draft slug override | trimmed, 200 characters, slugified on the server |
| Version string | semver, such as 1.2.3 |
| Entries per list call | 1 to 50, default 50 |
| Project name | 1 to 100 characters |
| Project website URL | a valid URL, 2000 characters |
| Chapter brief | 4000 characters |
| Chapter source paths | at least one path is required |
| Path segments | no empty, . or .. segment |
| Commit sha | 40 hex characters |
Break a bound and nothing is written: the entries endpoints answer 400 with the code VALIDATION_ERROR and the flattened field errors under details, before any insert runs. Two nouns used below: a manual is the chapter set generated from your repository and rechecked against it, and a version is one labelled snapshot of that manual with the commits its claims were written against.
Entry types and statuses
An entry takes one of five types: feature, fix, improvement, breaking, announcement. The type is optional and may be null. An entry is either a draft or published, and a list call narrows by status=draft or status=published, or by type set to one of the five.
A manual chapter carries one of four states: draft, flagged, approved, published. A request may ask for only three of them: draft, approved, published. The flagged state comes from the self-check and from nothing you send.
The error envelope and codes
Every failure uses one envelope:
{ "error": { "code": "NOT_FOUND", "message": "Project 'acme-app' not found" } }
VALIDATION_ERROR, status 400. The schema rejected the payload or the query string, and details carries the flattened field errors. Send a 60,000-character body and you hit the 50,000-character cap: the response is this code and no entry is created.
CONFLICT, status 409. The write collided with an entry that already exists, and the message names the collision.
NOT_FOUND, status 404. The project slug does not resolve inside your organization: Project 'acme-app' not found.
SERVER_ERROR, status 500. The write failed for a reason that is ours, and the message is passed through.
Two more you will meet. A key missing a capability gets 403 and API key lacks publish permission. Asking to publish in the same call that creates the entry is checked before the insert, so a refused publish never leaves a draft behind. A successful create answers 201 with the entry under data.
Rate limits by channel
| Channel | Window |
|---|---|
| Widget data reads | 60 per minute |
| Widget analytics | 120 per minute |
| Subscribe, per IP | 5 per hour |
| Subscribe, per email address | 3 per hour |
| Unsubscribe | 20 per hour |
| Owner lifecycle opt-out | 20 per hour |
| API key requests | 60 per minute |
| Dashboard AI | 60 per minute |
| Webhooks | 200 per minute |
The API channel counts per organization, not per key. Over the limit, the response is 429 with the code RATE_LIMITED and the message Too many requests. Please slow down and try again shortly. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a rejected one adds Retry-After in seconds. The limit check runs before the capability check, so an over-limit caller gets the 429 whatever the key may do. When no limiter is configured the check reports an infinite limit and the request proceeds.
Keys and plans
A key holds capabilities drawn from four names: read, write, publish, delete. Every key must include read, and a new key defaults to all four. Send an empty array and you get both refusals back: At least one permission required and Every key needs the read permission.
Writing through the API is open on every plan. Free, Pro and Team all carry it, and there is no paid gate on a push.