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

Mouve Developers
API reference

Posts

Creating, reading, and deleting posts and replies. Paths, scopes, request and response shapes.

Create a post or a reply

POST /public/v1/posts

Scope posts.write — OAuth 2.1 token or personal access token.

Send audience for a top-level post — it is required and never defaulted. Send in_reply_to_post_id for a reply, and then audience is forbidden: a reply inherits the thread visibility. Reply text is capped at 2000 characters against 5000 for a top-level post. Pass an Idempotency-Key header so a retry cannot double-post. media_ids is validated but not yet usable: the media endpoints are not part of this release, so any id supplied is rejected with 422 MEDIA_NOT_FOUND. Post without media until they ship.

Headers

NameTypeRequiredNotes
Idempotency-KeystringnoSend the same key to retry a create safely: the first response is stored and replayed verbatim with Idempotency-Replayed: true. Reusing a key with a different body is 422; a duplicate still in flight is 409. At most 255 characters, matches ^[!-~]{1,255}$

Request body

FieldTypeRequiredNotes
textstringyes1–5000 characters
audienceeveryone | following | only_meno—
media_idsarray of string (uuid)noat most 5 items
in_reply_to_post_idstring (uuid)no—

Example

curl -X POST "https://api.mouve.it/public/v1/posts" \
  -H "Authorization: Bearer $MOUVE_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"text":"Hello from the Mouve API","audience":"everyone"}'

Response 201

PublicPostDto

FieldTypeRequiredNotes
idstringyes—
textstringyes—
authorPublicUserRefDtoyes—
created_atstringyesISO 8601 timestamp in UTC.
audienceeveryone | following | only_meyes—
in_reply_to_post_idstring | nullyesThe post this one replies to; null on a top-level post.
mediaarray of PublicMediaRefDtoyes—
metricsobjectyes—
metrics.like_countnumberyes—
metrics.reply_countnumberyes—
metrics.repost_countnumberyes—
metrics.view_countnumberyes—
permalinkstringyesAbsolute URL, computed server-side: {APP_URL}/{username}/post/{id}.
app_idstring | nullyesProvenance from metadata.agent; null = first-party.

Errors

Beyond the shared responses:

Get a post

GET /public/v1/posts/{id}

Scope posts.read — OAuth 2.1 token or personal access token.

Reads a single post by id, visibility-checked for the authorizing user. A post that exists but is not visible to them is a 404, identical to one that never existed — the API does not confirm the existence of content you cannot read.

Path parameters

NameTypeRequiredNotes
idstring (uuid)yes—

Example

curl -X GET "https://api.mouve.it/public/v1/posts/11111111-2222-4333-8444-555555555555" \
  -H "Authorization: Bearer $MOUVE_TOKEN"

Response 200

PublicPostDto

FieldTypeRequiredNotes
idstringyes—
textstringyes—
authorPublicUserRefDtoyes—
created_atstringyesISO 8601 timestamp in UTC.
audienceeveryone | following | only_meyes—
in_reply_to_post_idstring | nullyesThe post this one replies to; null on a top-level post.
mediaarray of PublicMediaRefDtoyes—
metricsobjectyes—
metrics.like_countnumberyes—
metrics.reply_countnumberyes—
metrics.repost_countnumberyes—
metrics.view_countnumberyes—
permalinkstringyesAbsolute URL, computed server-side: {APP_URL}/{username}/post/{id}.
app_idstring | nullyesProvenance from metadata.agent; null = first-party.

Errors

Only the shared responses.

List replies to a post

GET /public/v1/posts/{id}/replies

Scope posts.read — OAuth 2.1 token or personal access token.

Newest first, cursor-paginated. The parent post must be visible to the authorizing user: an unreadable thread is a 404 here exactly as it is on the post itself, so a hidden thread never leaks through its reply list.

Path parameters

NameTypeRequiredNotes
idstring (uuid)yes—

Query parameters

NameTypeRequiredNotes
limitintegerno1–100, defaults to 20
cursorstringnoat most 512 characters

Example

curl -X GET "https://api.mouve.it/public/v1/posts/11111111-2222-4333-8444-555555555555/replies" \
  -H "Authorization: Bearer $MOUVE_TOKEN"

Response 200

PublicPostListDto

FieldTypeRequiredNotes
dataarray of PublicPostDtoyes—
metaobjectyesnext_cursor is null on the last page.
meta.next_cursorstring | nullyes—

Errors

Beyond the shared responses:

StatusCode
400INVALID_CURSOR

Delete a post

DELETE /public/v1/posts/{id}

Scope posts.write — OAuth 2.1 token or personal access token.

Soft-deletes a post the authorizing user owns and returns 204 with no body. Deleting a post that belongs to someone else is a 403; a second delete of the same post is a 404, so it is not idempotent — treat the 404 as "already gone" rather than retrying.

Path parameters

NameTypeRequiredNotes
idstring (uuid)yes—

Example

curl -X DELETE "https://api.mouve.it/public/v1/posts/11111111-2222-4333-8444-555555555555" \
  -H "Authorization: Bearer $MOUVE_TOKEN"

Response 204

No body.

Errors

Beyond the shared responses:

StatusCode
403FORBIDDEN