Browse documentation

Conventions

Behaviour that holds across every endpoint, so the reference does not have to repeat it 101 times.

Requests

All requests are HTTPS. Bodies are JSON with Content-Type: application/json, except file uploads, which are covered below. Paths are case-sensitive. Unknown fields in a request body are rejected rather than ignored, so a typo in a field name surfaces as a 400 instead of silently doing nothing.

Status codes

200Success. The body carries the resource or result.
201Created. Returned by endpoints that create a record.
400The request was malformed or failed validation. Fix and resend; retrying unchanged will not help.
401Missing, expired or rejected token. Mint a new one; if it persists, assume revoked.
403Authenticated but not permitted — usually a record belonging to another organization.
404No such route, or no such record visible to your organization. These are deliberately indistinguishable.
429Rate limited. Honour Retry-After.
500A fault on our side. Safe to retry with backoff; report it with the apigw-requestid.

403 and 404 deserve a note. Asking for a record that belongs to another organization returns the same response as asking for one that does not exist. That is intentional — the alternative lets a caller map out which record ids are real by watching which error comes back.

Error responses

Errors carry a JSON body. Read the status code first and the message second: messages are written for a human reading a log and may change, while status codes are contractual.

json
{
  "message": "Unauthorized"
}

The token endpoint on movik.us uses a richer shape with a stable error code you can branch on — see token endpoint errors.

File uploads

Uploads are a three-step flow rather than a multipart post, because the file goes to S3 directly and never transits the API. This keeps large documents off the request path.

1. Ask for a pre-signed URL with POST /files. You get back a fileKey and an uploadUrl.
2. PUT the raw bytes to that URL. Do not attach your bearer token — the signature in the URL is the authorization, and adding a token makes S3 reject the upload.
3. Confirm with POST /files/confirm so Movik records the upload as complete. A file that is never confirmed is treated as abandoned.

bash
# 1. request a URL
curl -X POST https://api.dev.movik.us/files \
  -H "Authorization: Bearer $ID_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"folder":"leads","originalFileName":"carrier.jpg","contentType":"image/jpeg"}'

# 2. upload the bytes — no Authorization header
curl -X PUT "$UPLOAD_URL" \
  -H 'Content-Type: image/jpeg' \
  --data-binary @carrier.jpg

# 3. confirm
curl -X POST https://api.dev.movik.us/files/confirm \
  -H "Authorization: Bearer $ID_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"fileKey":"'"$FILE_KEY"'"}'

See the Files reference for exact fields.

Retries and idempotency

GET and DELETE are safe to retry. POST is not idempotent unless an endpoint says so, so a retry after a timeout can create a second record. Where you cannot tolerate a duplicate, retry with a read first: look up whether the record landed, then decide.

Retry 500 and 429 with exponential backoff. Do not retry 400, 403 or 404 — the answer will not change.

Reporting a problem

Every response carries an apigw-requestid header identifying that exact invocation. Include it with the path, the status and the approximate time when you write to support@movik.us. With it we can find your request in the logs directly; without it we are guessing.