Skip to main content

Overview

Stories are content pieces published by profiles. They support multiple kinds (article, announcement, status, etc.) and can be published to multiple profiles.

Story Kinds

  • article - Long-form blog post or article
  • announcement - Important announcement
  • news - News update
  • status - Short status update
  • content - General content
  • presentation - Presentation or slides
  • activity - Event or activity (meetup, workshop, conference, etc.)

List Stories

GET /{locale}/stories
List all published stories with pagination.
locale
string
required
Locale code
filter_kind
string
Comma-separated story kinds to filter by
limit
integer
default:"25"
Number of stories per page
offset
integer
default:"0"
Number of stories to skip
curl "http://localhost:8080/en/stories?filter_kind=article,announcement&limit=10"
Response:
{
  "data": [
    {
      "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
      "slug": "introducing-aya",
      "kind": "article",
      "title": "Introducing Aya",
      "summary": "A new open-source community platform",
      "content": "# Introducing Aya\n\n...",
      "story_picture_uri": "https://cdn.aya.is/stories/cover.jpg",
      "published_at": "2024-01-15T10:30:00Z",
      "author_profile_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
      "visibility": "public",
      "feat_discussions": true
    }
  ],
  "cursor": {
    "next": "eyJvZmZzZXQiOjEwfQ==",
    "has_more": true
  }
}

Get Story by Slug

GET /{locale}/stories/{slug}
Retrieve a single story by its unique slug.
slug
string
required
Story slug (e.g., introducing-aya)
curl "http://localhost:8080/en/stories/introducing-aya"
Response:
{
  "data": {
    "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
    "slug": "introducing-aya",
    "kind": "article",
    "title": "Introducing Aya",
    "summary": "A new open-source community platform",
    "content": "# Introducing Aya\n\nWe're excited to announce...",
    "story_picture_uri": "https://cdn.aya.is/stories/cover.jpg",
    "author_profile_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
    "published_at": "2024-01-15T10:30:00Z",
    "visibility": "public",
    "feat_discussions": true,
    "locale_code": "en",
    "created_at": "2024-01-14T15:20:00Z",
    "updated_at": "2024-01-15T10:30:00Z"
  }
}
id
string
Unique story ID (ULID)
slug
string
URL-friendly slug
kind
string
Story kind: article, announcement, news, status, content, presentation, activity
title
string
Story title
summary
string
Short summary
content
string
Full story content (Markdown)
story_picture_uri
string
Cover image URL
visibility
string
Story visibility: public, unlisted, private
feat_discussions
boolean
Whether discussions are enabled

Check Slug Availability

GET /{locale}/stories/{slug}/_check
Check if a story slug is available.
slug
string
required
Slug to check
exclude_id
string
Story ID to exclude (for updates)
story_id
string
Story ID for validation
published_at
string
Publication date (ISO 8601) for slug prefix validation
include_deleted
boolean
default:"false"
Include soft-deleted stories
Published stories require a date prefix in the slug (e.g., 2024-01-15-my-article). The API validates this automatically.
Response:
{
  "data": {
    "available": true,
    "message": "Slug is available",
    "severity": "info"
  }
}

Create Story

POST /{locale}/profiles/{slug}/_stories
Authentication Required - Must have contributor+ access to the profile
Create a new story for a profile.
slug
string
required
Profile slug to create story for
slug
string
required
Story slug (2-100 characters, lowercase, numbers, hyphens)
kind
string
required
Story kind: article, announcement, news, status, content, presentation, activity
title
string
required
Story title (max 200 characters)
summary
string
Short summary
content
string
required
Full story content (Markdown)
story_picture_uri
string
Cover image URL
publish_to_profiles
array
Array of profile IDs to publish to immediately
visibility
string
default:"public"
Story visibility: public, unlisted, private
feat_discussions
boolean
Enable discussions (inherits from profile default if not specified)
properties
object
Custom properties (JSON object) - used for activity-specific fields
curl -X POST "http://localhost:8080/en/profiles/my-blog/_stories" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "my-first-post",
    "kind": "article",
    "title": "My First Post",
    "summary": "Hello, world!",
    "content": "# Hello World\n\nThis is my first post.",
    "visibility": "public",
    "feat_discussions": true
  }'
Response:
{
  "data": {
    "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
    "slug": "my-first-post",
    "kind": "article",
    "title": "My First Post",
    "summary": "Hello, world!",
    "content": "# Hello World\n\nThis is my first post.",
    "visibility": "public",
    "feat_discussions": true,
    "author_profile_id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
    "created_at": "2024-03-07T10:30:00Z"
  }
}

Update Story

PATCH /{locale}/profiles/{slug}/_stories/{storyId}
Authentication Required - Must be story author or have contributor+ access
Update story main fields (slug, picture, properties, visibility).
storyId
string
required
Story ID (ULID) or slug
slug
string
required
New story slug
story_picture_uri
string
Cover image URL
visibility
string
Story visibility: public, unlisted, private
feat_discussions
boolean
Enable/disable discussions
properties
object
Custom properties (JSON object)
series_id
string
Story series ID (for grouping related stories)
sort_order
integer
Sort order within series
Managed StoriesStories synced from external sources (e.g., GitHub, RSS) cannot be edited directly. The API will return a 409 Conflict error.

Update Story Translation

PATCH /{locale}/profiles/{slug}/_stories/{storyId}/translations/{translationLocale}
Authentication Required
Update story content for a specific locale.
storyId
string
required
Story ID
translationLocale
string
required
Target locale for translation
title
string
required
Translated title
summary
string
Translated summary
content
string
required
Translated content (Markdown)

Delete Story

DELETE /{locale}/profiles/{slug}/_stories/{storyId}
Authentication Required
Soft-delete a story (can be restored).
Cannot delete stories with active publications. Unpublish from all profiles first.

Story Publications

List Publications

GET /{locale}/profiles/{slug}/_stories/{storyId}/publications
Authentication Required
List all profiles where this story is published. Response:
{
  "data": [
    {
      "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
      "story_id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
      "profile_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
      "profile_slug": "my-blog",
      "profile_title": "My Blog",
      "is_featured": true,
      "published_at": "2024-01-15T10:30:00Z"
    }
  ]
}

Add Publication

POST /{locale}/profiles/{slug}/_stories/{storyId}/publications
Authentication Required - Requires contributor+ access to target profile
Publish a story to a profile.
profile_id
string
required
Profile ID to publish to
Feature this story on the profile

Update Publication

PATCH /{locale}/profiles/{slug}/_stories/{storyId}/publications/{publicationId}
Authentication Required
Update publication settings (e.g., toggle featured).
Feature status

Remove Publication

DELETE /{locale}/profiles/{slug}/_stories/{storyId}/publications/{publicationId}
Authentication Required
Unpublish a story from a profile.

Auto-Translate Story

POST /{locale}/profiles/{slug}/_stories/{storyId}/translations/{targetLocale}/auto-translate
Authentication Required - Costs 5 points
Auto-translate story content using AI.
targetLocale
string
required
Target locale for translation
source_locale
string
required
Source locale to translate from
Cost: 5 points per translationAuto-translation uses AI to translate the title, summary, and content to the target locale.
curl -X POST "http://localhost:8080/en/profiles/my-blog/_stories/01ARZ3NDEKTSV4RRFFQ69G5FAV/translations/fr/auto-translate" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"source_locale": "en"}'
Response:
{
  "data": {
    "success": true
  }
}

Check Story Permissions

GET /{locale}/profiles/{slug}/_stories/{storyId}/_permissions
Authentication Required
Check if the authenticated user can edit the story. Response:
{
  "data": {
    "can_edit": true
  }
}

Build docs developers (and LLMs) love