API reference
Everything the dashboards do, your own systems can do. It is the same API the product is built on: there is no second, lesser API for customers.
- Base URL in development:
http://localhost:4000 - Authentication: a bearer token on every request. See Authentication.
- Format: JSON in, JSON out, UTF-8. Failures are problem envelopes.
- Versioning: every path is under
/v1/. - Request id: every response carries
x-request-id. Log it.
Your first request
Who am I: the one call every key may make, whatever its permissions.
curl http://localhost:4000/v1/whoami \
-H "Authorization: Bearer rw_your_key_here"
{
"accountId": "01M1VFRWE3A35H892VAAEKKDA6",
"accountName": "Enterprise 2",
"scopes": ["ingest:write", "posts:read", "media:write"],
"kind": "apikey"
}
Sending an event
The most common integration. Your system pushes something that happened; Reelwire draws it and posts it to every channel subscribed to that stream.
curl http://localhost:4000/v1/stream \
-H "Authorization: Bearer rw_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"streamId": "st_30472168d941",
"eventId": "01M2SQMKK3G1NVFXV31DCBVB92",
"occurredAt": "2026-09-18T07:55:00Z",
"locale": "en",
"data": {
"clipData": {
"headline": "Bund yields close at a three-week high",
"subline": "The ten-year settled at 2.41 per cent"
},
"metaData": { "title": "Bund yields close at a three-week high" }
}
}'
Three things to know about that body:
eventIdis a ULID and is the idempotency key. Sending the same one twice does not post twice, which is what makes a retry safe.- What belongs in
datais whatever the stream's template accepts, published as a schema at/v1/formats/template/{templateId}. Send that shape and it renders; send something else and you get a refusal naming the field. occurredAtis when the fact happened, not when you sent it.
Before sending anything real, POST /v1/stream/validate takes the same body and answers whether it
would have worked, without creating anything.
The whole worked example, with the real responses, is on Sending events.
Where to go next
| If you are | Read |
|---|---|
| Pushing data in from a producer | Sending events, then Streams and feeds |
| Receiving finished posts | Webhooks |
| Watching what happened | Posts and jobs |
| Scheduling posts somebody wrote | Post lists |
| Setting a workspace up by machine | Brands, Channels, Media library |
| Rendering a clip on its own | Renders and direct export |
| Generating a client | Templates and formats |
| Looking for one route | Every endpoint |
Two conventions worth knowing up front
A mutation is a POST to a verb, not a DELETE. Removing a brand is POST /v1/brands/{id}/delete. This keeps every action addressable by a permission prefix and keeps
bodies available on actions that need one, such as the moveTo a brand deletion takes.
Lists come in two kinds. Logs are paged by the server; configuration comes back whole. See Lists and paging.