API reference
Every endpoint of the Mouve public API: paths, scopes, request and response shapes, and the errors each one returns.
This reference is generated from the code that serves the API — the
controllers, their validated request DTOs, and the frozen wire contract.
The machine-readable OpenAPI 3.1 document is at
/openapi.json; point a code generator at it rather than
transcribing these tables.
Calling any endpoint
Base URL: https://api.mouve.it. Every request needs a bearer
credential and the scopes listed for the operation:
curl https://api.mouve.it/public/v1/me \
-H "Authorization: Bearer $MOUVE_TOKEN"Scopes are exact-match — holding posts.write grants nothing that requires
posts.read. See scopes for the full catalog, and
authentication for how to obtain a credential.
Endpoints
| Method | Path | Scope | Summary |
|---|---|---|---|
| GET | /public/v1/me | profile.read | Get the authorizing user |
| GET | /public/v1/users/{username} | profile.read | Get a user by username |
| GET | /public/v1/users/{username}/posts | posts.read | List a user's posts |
| POST | /public/v1/posts | posts.write | Create a post or a reply |
| GET | /public/v1/posts/{id} | posts.read | Get a post |
| GET | /public/v1/posts/{id}/replies | posts.read | List replies to a post |
| DELETE | /public/v1/posts/{id} | posts.write | Delete a post |
| GET | /public/v1/timeline | posts.read | Read the authorizing user's timeline |
Shared responses
Every operation can return these, from the shared request path rather than from anything specific to the endpoint:
| Status | Code |
|---|---|
401 | UNAUTHENTICATED |
401 | TOKEN_EXPIRED |
401 | TOKEN_REVOKED |
403 | INSUFFICIENT_SCOPE |
403 | TOKEN_NOT_PERMITTED |
403 | ACCOUNT_SUSPENDED |
403 | ONBOARDING_REQUIRED |
403 | CLIENT_DISABLED |
404 | NOT_FOUND |
429 | RATE_LIMITED |
500 | INTERNAL |
A 404 is also what the whole surface returns while the API is not yet
enabled for your account. See errors for the complete
registry and the status discipline.
Schemas
PublicProblemDto
RFC 9457 application/problem+json body every /public/v1 error uses. type is a stable URI per code (https://developers.mouve.it/errors/\<kebab>), code is the machine contract, request_id correlates with API logs. errors is present on VALIDATION_FAILED only.
| Field | Type | Required | Notes |
|---|---|---|---|
type | string | yes | — |
title | string | yes | — |
status | number | yes | — |
code | VALIDATION_FAILED | INVALID_CURSOR | INVALID_IDEMPOTENCY_KEY | UNAUTHENTICATED | TOKEN_EXPIRED | TOKEN_REVOKED | INSUFFICIENT_SCOPE | VENUE_NOT_VERIFIED | APPROVAL_REQUIRED | TOKEN_NOT_PERMITTED | FORBIDDEN | ACCOUNT_SUSPENDED | ONBOARDING_REQUIRED | CLIENT_DISABLED | NOT_FOUND | IDEMPOTENCY_IN_FLIGHT | SLOT_UNAVAILABLE | CHANGESET_STALE | CHANGESET_OPEN | CONFLICT | ENDPOINT_RETIRED | PAYLOAD_TOO_LARGE | IDEMPOTENCY_BODY_MISMATCH | OUTSIDE_HOURS | AUDIENCE_UNAVAILABLE | MEDIA_NOT_FOUND | MEDIA_ALREADY_ATTACHED | MEDIA_URL_INVALID | MEDIA_URL_BLOCKED | MEDIA_FETCH_FAILED | MEDIA_TOO_LARGE | MEDIA_UNSUPPORTED_TYPE | MEDIA_VIDEO_UNSUPPORTED | RATE_LIMITED | USAGE_LIMIT_EXCEEDED | MEDIA_QUOTA_EXCEEDED | INTERNAL | UNAVAILABLE | VENUE_AGENT_WRITES_DISABLED | yes | — |
detail | string | yes | — |
request_id | string | yes | — |
errors | array of object | no | — |
errors[].field | string | yes | — |
errors[].message | string | yes | — |
retry_after_seconds | number | no | Extension members present on 429 responses only. |
scope | string | no | — |
window | string | no | — |
limit | number | no | — |
fix | string | no | Agent-readable remedy ("send starts_at on a 30-minute boundary"). Optional on every code; the venue codes always carry one. |
docs_url | string | no | Link to the docs for this code. |
approval_url | string | no | APPROVAL_REQUIRED only: where the owner approves. Not retried. |
PublicMeDto
GET /public/v1/me — the authorizing user's own public identity.
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | — |
username | string | yes | Handle without the leading @, as it appears in a permalink. |
display_name | string | null | yes | — |
avatar_url | string | null | yes | — |
bio | string | null | yes | — |
created_at | string | yes | ISO 8601 timestamp in UTC. |
verified | boolean | yes | — |
PublicUserDto
GET /public/v1/users/:username — viewer-projected. No email, date of birth, sex, height, or weight is ever returned, under any scope.
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | — |
username | string | yes | Handle without the leading @, as it appears in a permalink. |
display_name | string | null | yes | — |
avatar_url | string | null | yes | — |
bio | string | null | yes | — |
created_at | string | yes | ISO 8601 timestamp in UTC. |
verified | boolean | yes | — |
private | boolean | yes | The account gates its content behind follow approval. |
PublicUserRefDto
Embedded author reference on a post.
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | — |
username | string | yes | — |
display_name | string | null | yes | — |
avatar_url | string | null | yes | — |
verified | boolean | yes | — |
PublicMediaRefDto
Media attached to a post. id is null for media uploaded through the Mouve apps rather than the API; API-uploaded media carry a real id once the media endpoints ship. width, height, and content_type are null when unknown, and may become non-null later — a nullable field gaining a value is not a breaking change.
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | null | yes | — |
url | string | yes | — |
width | number | null | yes | — |
height | number | null | yes | — |
content_type | string | null | yes | — |
alt | string | null | yes | — |
PublicPostDto
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | — |
text | string | yes | — |
author | PublicUserRefDto | yes | — |
created_at | string | yes | ISO 8601 timestamp in UTC. |
audience | everyone | following | only_me | yes | — |
in_reply_to_post_id | string | null | yes | The post this one replies to; null on a top-level post. |
media | array of PublicMediaRefDto | yes | — |
metrics | object | yes | — |
metrics.like_count | number | yes | — |
metrics.reply_count | number | yes | — |
metrics.repost_count | number | yes | — |
metrics.view_count | number | yes | — |
permalink | string | yes | Absolute URL, computed server-side: {APP_URL}/{username}/post/{id}. |
app_id | string | null | yes | Provenance from metadata.agent; null = first-party. |
PublicPostListDto
| Field | Type | Required | Notes |
|---|---|---|---|
data | array of PublicPostDto | yes | — |
meta | object | yes | next_cursor is null on the last page. |
meta.next_cursor | string | null | yes | — |
PublicCreatePostRequest
| Field | Type | Required | Notes |
|---|---|---|---|
text | string | yes | 1–5000 characters |
audience | everyone | following | only_me | no | — |
media_ids | array of string (uuid) | no | at most 5 items |
in_reply_to_post_id | string (uuid) | no | — |