POST /api/v1/documents · Operation ID: createDocument
Create only after the user chooses to add/import content. In the personal workflow omit owner; an organisation owner requires separate management permissions. Save the returned ID and revision. Reuse an Idempotency-Key only for an identical retry of this creation.
Bearer token with documents:write. Resource access and effective policy still apply.
Replace all REPLACE_* placeholders and environment values with data for your authorized test account. Use a new UUID in IDEMPOTENCY_KEY for each logical action where shown; use the actual latest revision for If-Match. Examples of writes change real data if run.
curl --fail-with-body -X POST 'https://handwrites.io/api/v1/documents' \
-H "Authorization: Bearer $HANDWRITE_API_KEY" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-H 'Content-Type: application/json' \
--data '{"title":"Field notes","content":"The heron came back.","contentType":"text/plain"}'
| Name | Location | Required | Meaning |
|---|---|---|---|
Idempotency-Key | header | No | 1–255 visible ASCII characters (a UUID per operation). A retry with the same key and identical request within 24 hours replays the first 2xx response with Idempotent-Replayed: true; a different request with the key gets 422 idempotency_mismatch; a retry while the first runs gets 409 idempotency_in_progress. |
application/json (required).
| Field | Required | Meaning |
|---|---|---|
title | Yes | string |
content | No | Up to 4 MB. |
contentType | No | See API schema |
language | No | A BCP 47 language tag. |
owner | No | A team or class you manage, to create the document for it: team: or class:. |
| Status | Meaning | Body format |
|---|---|---|
| 201 | Created at revision 1. | application/json |
| 400 | invalid_request (the message names the field), validation_failed. | application/json |
| 401 | unauthorized: no token, or it's invalid, revoked or expired. | application/json |
| 403 | insufficient_scope, forbidden (you can see it but not do this), app_test_restricted, account_deleted (the account is scheduled for deletion; any request). | application/json |
| 404 | not_found: it doesn't exist or you can't see it (never 403 for documents you can't see). | application/json |
| 409 | conflict (changed meanwhile, already a member) or idempotency_in_progress (with Retry-After). | application/json |
| 413 | too_large (text over 4 MB) or too_long (audio over its limit). | application/json |
| 422 | limit_reached, idempotency_mismatch, unreadable_file, no_text, empty_document. | application/json |
| 429 | rate_limited (burst or daily cap) or quota_exceeded (no characters left). | application/json |
| 500 | internal_error. | application/json |
Use the paired API reference for complete request/response schemas. See API specification notes for rate limits, error handling, safe retries and additional policy/plan failures. For binary or empty responses, do not call a JSON parser.