The Mouve API is in active development and not yet live. Follow the changelog for the launch announcement.

Mouve Developers

Quickstart

Create a personal access token, read your profile, and publish your first post.

Not yet live

The endpoints on this page are not callable until the API launches. The examples show the exact launch contract so you can build against it now.

1. Create a token

Sign in to Mouve and open mouve.it/developers → API tokens. Create a token, pick the scopes it needs — this walkthrough needs profile.read and posts.write — and copy the token. It is shown once.

Tokens look like this (51 characters, prefix mouve_pat_):

mouve_pat_k9GmXw3vTqLpZr8dNs5cHbJf2yAeUo41xRiVE7wQzt9

Keep it out of your source. Everything below assumes:

export MOUVE_TOKEN="mouve_pat_..."

Building an app that other people connect? Use OAuth 2.1 instead — same API, same scopes, per-user consent.

2. Who am I?

curl https://api.mouve.it/public/v1/me \
  -H "Authorization: Bearer $MOUVE_TOKEN"
{
  "id": "0a1b2c3d-4e5f-6789-abcd-ef0123456789",
  "username": "alo",
  "display_name": "Alo Martin",
  "avatar_url": "https://mouve.it/api/img/avatars/0a1b2c3d.webp",
  "bio": "Building Mouve.",
  "created_at": "2025-11-02T09:14:33Z",
  "verified": true
}

All ids in the API are UUIDs. Responses are snake_case JSON — single resources are returned bare, lists come wrapped in {"data": [...], "meta": {...}} (see pagination).

3. Publish a post

curl -X POST https://api.mouve.it/public/v1/posts \
  -H "Authorization: Bearer $MOUVE_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3f2b6c1e-8a4d-4e9b-9c7a-5d0e1f2a3b4c" \
  -d '{
    "text": "Shipped my first post through the Mouve API.",
    "audience": "everyone"
  }'

Two things are load-bearing here:

  • audience is required on a new post — one of everyone, following, or only_me. It is never defaulted: omitting it is a 400 VALIDATION_FAILED. (On a reply — in_reply_to_post_id set — audience is forbidden instead: replies inherit the thread's visibility.)
  • Idempotency-Key makes the create safe to retry: the same key replays the original response instead of creating a duplicate. See idempotency.

The response is the created post:

{
  "id": "7c8d9e0f-1a2b-4c3d-8e9f-0a1b2c3d4e5f",
  "text": "Shipped my first post through the Mouve API.",
  "author": {
    "id": "0a1b2c3d-4e5f-6789-abcd-ef0123456789",
    "username": "alo",
    "display_name": "Alo Martin",
    "avatar_url": "https://mouve.it/api/img/avatars/0a1b2c3d.webp"
  },
  "created_at": "2026-08-29T10:12:44Z",
  "audience": "everyone",
  "in_reply_to_post_id": null,
  "media": [],
  "metrics": { "like_count": 0, "reply_count": 0, "repost_count": 0, "view_count": 0 },
  "permalink": "https://mouve.it/alo/post/7c8d9e0f-1a2b-4c3d-8e9f-0a1b2c3d4e5f",
  "app_id": null
}

To attach images, upload them first via POST /public/v1/media (by URL or multipart file, up to 5 per post) and pass the returned ids as media_ids.

4. When something goes wrong

Errors are RFC 9457 application/problem+json. For example, calling a write endpoint with a read-only token:

{
  "type": "https://developers.mouve.it/errors/insufficient-scope",
  "title": "Insufficient scope",
  "status": 403,
  "code": "INSUFFICIENT_SCOPE",
  "detail": "This request requires the posts.write scope.",
  "request_id": "req_8f3a1c2b9d4e"
}

code is stable and machine-matchable; request_id is what to quote when reporting a problem.

Next