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. Send your own ULID in that header and Reelwire uses it, so your logs and ours share one id.
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",
"resource": null
}
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.- A picture is a file from your media library, written
media://and its id or name. A web address is refused.
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 |
| Handing your posts on to your own participants (Enterprise) | Syndication |
| Managing colleagues, or reading the plan | Team and plan |
| Watching what happened | Posts and jobs |
| Scheduling posts somebody wrote | Post lists |
| Setting a workspace up by machine | Brands, Channels, Media library |
| Making pictures, videos, fonts or texts with AI | AI assistant |
| Rendering a clip on its own | Renders and direct export |
| Generating a client | Templates and formats |
| Looking for one route | Every endpoint |
| Choosing what a key may do | Permissions |
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.