# Post story

`POST /story.post`

## Description

Posts a story to your Roam. Stories are short photo or video updates that appear
above your profile picture for your teammates, and expire 24 hours after posting.

## Posting Flow

1. Create the media asset with [asset.create](/docs/roam-api/create-asset) using
   `purpose: "story"`, and upload the file bytes using the returned upload instructions.
2. Call this endpoint with the `assetId` (and an optional `caption`).

The media must be a photo or a video (videos up to 2.5 minutes; media is optimized
to portrait 1080×1920). If the upload is still processing — typical for videos in
the first seconds after upload — this endpoint returns a 400 with a "still
processing" message; retry after a short delay.

The media must outlive the story's 24-hour lifetime, so post within about 23 hours
of creating the asset (story assets expire about 48 hours after creation); older
assets are rejected and must be recreated.

**Access:** Personal only. Stories are always posted as the authenticated user —
a story appears above *your* profile picture, and there is no bot persona surface
for stories — so organization tokens are rejected.

**Required scope:** `chat:send_message` or `chat:write` (the same permission that
gates sending a chat message)

---

**OpenAPI Spec:** [openapi.json](https://developer.ro.am/openapi.json)

## Authentication

```
Authorization: Bearer YOUR_API_KEY
```

## Request Body

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `assetId` | string | Yes | ID of a processed asset created via [asset.create](/docs/roam-api/create-asset) with `purpose: "story"`. The asset must be owned by the authenticated user.  |
| `caption` | string | No | Optional caption displayed with the story. |

### Example Request

```json
{
  "assetId": "019be84b-0fa8-788f-8850-96de4cc39130",
  "caption": "Greetings from the offsite 👋"
}
```

## Responses

### 200 - The story was posted.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `itemId` | string | No | ID of the created story item. |
| `chatId` | string | No | ID of the Roam's story chat the story was posted into. |
| `expiresAt` | string | No | When the story expires (24 hours after posting). |


#### Example Response

```json
{
  "itemId": "019be84b-1234-7890-8850-96de4cc39130",
  "chatId": "757dfe66-37b4-4772-baa5-8c86ec68c176",
  "expiresAt": "2026-07-10T15:04:05Z"
}
```

### 400 - Bad request. Common causes:
- Missing or malformed `assetId`
- Asset not found, or not owned by the authenticated user
- Asset was not created with `purpose: "story"`
- Asset is still processing (retry shortly) or failed processing
- Asset would expire before the story's 24-hour lifetime ends (post within about 23 hours of creating the asset)
- Media is not a photo or video
- `caption` exceeds 2,048 characters


### 401 - Presented invalid authentication credentials.

### 403 - Forbidden. An organization token was used (stories require a personal access
token), or the token lacks the `chat:send_message`/`chat:write` scope.


### 405 - An unsupported method was requested.

### 500 - An internal error occured.

---

*Machine-readable API documentation.*
*Full documentation: https://developer.ro.am/docs/roam-api/post-story*
