Docs

Posting

One request, every network. Each target can carry its own text, media and options.

Now

POST /v1/posts
curl -X POST "https://api.usecrier.com/v1/posts" \
  -H "Authorization: Bearer $CRIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Our autumn collection is here 🍂",
    "targets": [
      {
        "accountId": "acc_ig"
      },
      {
        "accountId": "acc_li"
      }
    ]
  }'

Scheduled

Add scheduledFor in ISO 8601 with a timezone offset.

POST /v1/posts
curl -X POST "https://api.usecrier.com/v1/posts" \
  -H "Authorization: Bearer $CRIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "We open Friday at 9",
    "scheduledFor": "2026-10-30T09:00:00+01:00",
    "targets": [
      {
        "accountId": "acc_ig"
      }
    ]
  }'

You can cancel it before it goes out with POST /v1/posts/{id}/cancel.

Queued

With queue: true it takes the next free slot of the profile’s queue. Every account must belong to the same profile.

POST /v1/posts
curl -X POST "https://api.usecrier.com/v1/posts" \
  -H "Authorization: Bearer $CRIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Tip of the day",
    "queue": true,
    "targets": [
      {
        "accountId": "acc_ig"
      }
    ]
  }'

Draft

With draft: true it is saved without posting or scheduling.

Text and media per network

Each target can replace the post’s text (content) and media (media), and carry its network’s options under the network’s key (instagram, youtube, tiktok…). See Network options.

POST /v1/posts
curl -X POST "https://api.usecrier.com/v1/posts" \
  -H "Authorization: Bearer $CRIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "How our jacket is made",
    "media": [
      {
        "type": "video",
        "url": "https://cdn.acme.com/jacket.mp4"
      }
    ],
    "targets": [
      {
        "accountId": "acc_ig",
        "instagram": {
          "format": "reel",
          "firstComment": "#autumn #fashion"
        }
      },
      {
        "accountId": "acc_yt",
        "youtube": {
          "title": "How our jacket is made",
          "visibility": "public"
        }
      },
      {
        "accountId": "acc_x",
        "content": "How our jacket is made 🧵",
        "x": {
          "thread": [
            "1/ It starts in the workshop…"
          ]
        }
      }
    ]
  }'

Statuses

StatusMeaning
draftDraft, no date.
pending_approvalWaiting for an owner or admin to approve it. It does not go out until then.
scheduledScheduled or queued, waiting for its time.
publishingBeing sent to the networks.
publishedLive everywhere. Each target has its url.
partialLive on some, failed on others. Retry the failed ones with POST /v1/posts/{id}/retry.
failedLive nowhere. Each target explains why in error.
cancelledCancelled before going out, or taken down everywhere.

Editing

While it is not live (draft, scheduled, failed or cancelled) you can change anything with PATCH /v1/posts/{id}. What you leave out stays; targets replaces the whole list.

PATCH /v1/posts/pst_7q1w0e
curl -X PATCH "https://api.usecrier.com/v1/posts/pst_7q1w0e" \
  -H "Authorization: Bearer $CRIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "We open Friday at 10",
    "scheduledFor": "2026-10-30T10:00:00+01:00"
  }'

With draft: false a draft goes out: now, at scheduledFor or in the queue.

Once live, only the text can change, and only on networks that allow it: X (Premium accounts, within the first hour), Facebook, LinkedIn, YouTube, Pinterest, Google Business, Telegram, Discord and Reddit.

POST /v1/posts/pst_7q1w0e/edit
curl -X POST "https://api.usecrier.com/v1/posts/pst_7q1w0e/edit" \
  -H "Authorization: Bearer $CRIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Corrected text"
  }'

Approval

With requiresApproval: true the post stays in pending_approval: it does not go out until someone approves it. If the workspace requires approval (PATCH /v1/workspace with requireApproval: true, or from Team in the dashboard), members’ posts always go through it. Owners, admins and API keys skip it unless they ask for it.

POST /v1/posts
curl -X POST "https://api.usecrier.com/v1/posts" \
  -H "Authorization: Bearer $CRIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "New collection",
    "scheduledFor": "2026-11-06T09:00:00+01:00",
    "requiresApproval": true,
    "targets": [
      {
        "accountId": "acc_ig"
      }
    ]
  }'

An owner, an admin or an API key decides with POST /v1/posts/{id}/review. Approved, it is scheduled for its date, goes to the queue if it asked for it, or goes out now if its date passed while it waited. Rejected, it goes back to draft with the note, and your webhook gets post.rejected.

POST /v1/posts/pst_7q1w0e/review
curl -X POST "https://api.usecrier.com/v1/posts/pst_7q1w0e/review" \
  -H "Authorization: Bearer $CRIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "decision": "reject",
    "note": "Change the cover photo"
  }'

Editing it while it waits does not publish it: it stays pending. Its author can withdraw it with POST /v1/posts/{id}/cancel.

Recycle

A post that works can go out again on its own: every N weeks or months, as a new post. It stops at maxCopies or after until, and variations are used in turn so the text is not always the same.

PUT /v1/posts/pst_7q1w0e/recycling
curl -X PUT "https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling" \
  -H "Authorization: Bearer $CRIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "every": 2,
    "unit": "month",
    "maxCopies": 6,
    "variations": [
      "The autumn classic is back 🍂",
      "In case you missed it: our autumn classic"
    ]
  }'

Metrics

GET /v1/posts/{id}/metrics returns impressions, reach, views, likes, comments, shares, saves and clicks, in total and per account. They arrive a few minutes after posting; until then it returns null. Each network reports its own: the rest are 0.

Account groups

Save account selections (for example "All of Acme") with POST /v1/account-groups and use them when importing a CSV or from the dashboard.

POST /v1/account-groups
curl -X POST "https://api.usecrier.com/v1/account-groups" \
  -H "Authorization: Bearer $CRIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "All of Acme",
    "accountIds": [
      "acc_ig",
      "acc_li",
      "acc_x"
    ]
  }'

Taking down and deleting

🚧 Not ready yet

We're finishing building it

Crier is in early access. Leave your email and you'll be among the first in, with launch terms.

or with your email

No spam. We'll only write to give you access.

You're on the list!

We'll write to you as soon as your access is ready.