# Add Post

Source: https://help.zira.us/developers/api-reference/add-post
Summary: Create a feed post in a target channel under an API-key integration context.
Updated: 2026-08-06

## `POST /post`

Use this endpoint when an external system needs to publish an update into a Zira channel. The request can send a single post object or an array of post objects.

## Authentication

```http
x-api-key: <your-api-key>
Content-Type: application/json
```

See [API Authentication](/developers/api-reference/api-authentication) for how to create a key.

## Request body

Send either one post object or an array of post objects.

```json
{
  "title": "Hello world!",
  "content": "This is my message",
  "toChannelId": "14727",
  "skipNotifications": true
}
```

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `title` | string | no | Optional title shown above the post content. |
| `content` | string | yes | Main post body text. |
| `toChannelId` | string | yes | Target channel ID where the post will be created. |
| `skipNotifications` | boolean | no | Set to true to avoid notifying followers about this post. |
| `payload` | object | no | Optional structured payload attached to the post. |
| `groupingKey` | string | no | Optional grouping key for related post events. |
| `imageId` | string | no | Optional image asset reference to attach to the post. |
| `priorityId` | string | no | Optional priority reference for the post. |
| `hashtags` | string[] | no | Optional hashtags to attach to the post. |
| `ctas` | object[] | no | Optional call-to-action objects attached to the post. |

## Response

`200 OK`

Returns the ID of the post that was created, as a bare number under `data`. The post itself is not echoed back, and there is no public endpoint to read it again — so keep this ID if you need to reference the post later.

```json
{
  "data": 240872
}
```

| Field | Type | Description |
| --- | --- | --- |
| `data` | number | ID of the newly created post. It comes back as a JSON number, even though every ID you send in the request body has to be a string. |

### Good to know

- One post per request. Send a single object — an array holding exactly one post also works, but an array of two or more is not supported and fails.
- An empty array creates nothing and returns `{}`, with no `data` key at all.
- Zira sets `fromChannelId` and `postTypeId` itself, from the API key context. Do not send them: any field outside the list above is rejected with `400` and `internalErrorCode` `01-004`.
- Followers are notified after the post is created, so the post exists even when notification delivery fails. Send `skipNotifications: true` to create the post quietly.

## Errors

Failures return a JSON body with a `message` and an `internalErrorCode`, at the status shown below. Whenever the underlying error carries structured detail — which every schema-validation failure does — the body is replaced with a generic `Internal server error.` / `02-001` pair while the real status code is kept. Branch on the HTTP status and on `internalErrorCode`; never parse the message text.

```json
{
  "message": "Internal server error.",
  "internalErrorCode": "02-001"
}
```

| Status | Meaning |
| --- | --- |
| `400` | The request failed validation — a missing required field, a field the schema does not allow, an unparseable body, a value out of range, or a malformed `lastValue`. |
| `401` | The API key resolved to a user context that is not allowed to read or write the record you asked for. |
| `403` | The `x-api-key` header is missing or is not a recognised key. API Gateway rejects the call before the endpoint runs, so the body is only `{"message":"Forbidden"}`. |
| `409` | The write conflicts with an existing record, or it references a record that does not exist. |
| `429` | The API key exceeded the rate limit or quota on its usage plan. Also returned by API Gateway rather than the endpoint. |
| `500` | Unexpected server error, or the database returned no result where one was required. |
