Skip to main content

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:

  • eventId is 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 data is 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.
  • occurredAt is 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 areRead
Pushing data in from a producerSending events, then Streams and feeds
Receiving finished postsWebhooks
Handing your posts on to your own participants (Enterprise)Syndication
Managing colleagues, or reading the planTeam and plan
Watching what happenedPosts and jobs
Scheduling posts somebody wrotePost lists
Setting a workspace up by machineBrands, Channels, Media library
Making pictures, videos, fonts or texts with AIAI assistant
Rendering a clip on its ownRenders and direct export
Generating a clientTemplates and formats
Looking for one routeEvery endpoint
Choosing what a key may doPermissions

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.