Skip to main content

Create document

MethodPath
POST/document

Authentication · Access policies · Files and documents

Creates a document and returns a signed form for uploading its file. Use it for every new file. The file does not pass through Ovok: you send it to file storage with the form this route returns.

Auth: Bearer token. Any signed-in user can call it, if the access policy allows Binary:create and DocumentReference:create. Scope: The document is created in the caller's project (from the token). The caller's profile is recorded as the author.

Request​

Body​

NameTypeRequiredDescription
fileNamestringYesName of the file. Stored as the document title and used as the download name. At least 1 character.
contentTypestringYesMIME type of the file. One of image/jpeg, image/jpg, image/png, image/gif, image/webp, application/pdf, application/json, application/xml, text/plain, text/csv, video/mp4, video/webm, audio/mpeg, audio/wav. Matched exactly, so text/plain; charset=utf-8 is rejected.
isPublic"true" | "false"NoA string, not a JSON boolean. Default "false". "true" also gives the document a public token.

Behaviour​

  • Creates an empty Binary for the file, then a DocumentReference with status current, fileName as the attachment title, contentType as the attachment type, and the caller's profile as author. The two are created one after the other, not in one transaction. If the second fails, an empty Binary can remain.
  • With isPublic set to "true", a public token is added and returned as publicToken. Anyone who has it can download the file with GET /document/public/:token.
  • The answer holds uploadOptions: an upload url and the form fields. Send a multipart/form-data POST to uploadOptions.url. Add every entry of uploadOptions.fields as a form field, exactly as returned, then add the file as the last part, named file. The set of fields can change, so do not hard-code it.
  • The form is valid for 10 minutes after it is issued and accepts files from 0 bytes up to 5 GB (5,368,709,120 bytes). File storage answers the upload, not Ovok. A 2xx answer means the file is stored. If the form has expired, call POST /document/:id to get a new one for the same document.
  • The form limits the size of the file only. It does not check that the file matches contentType.
  • The document exists as soon as this call returns, even if you never upload the file. Delete it yourself if you abandon the upload.
  • The route is rate limited per user, per client IP address, in a one-minute window. Admins can make 20 calls a minute. Practitioners, patients, related persons and client applications can make 10. Super admins are not limited on this route. Every call counts, including calls that fail validation.

Example​

curl -X POST 'https://api.sandbox.ovok.com/document' \
-H "Authorization: Bearer ${OVOK_TOKEN}" \
-H 'Content-Type: application/json' \
-d '{
"fileName": "cat.png",
"contentType": "image/png",
"isPublic": "false"
}'

Then upload the file with the returned form. Send every field from uploadOptions.fields, and file last:

curl -X POST 'https://storage.example.com/ovok-files' \
-F 'key=binary/5d2a9c64-7e1b-4830-b6f5-9a3c1e8d7b02/8c5e7a21-4b9d-4f36-a1c8-0d2e6b9f3a54' \
-F '<next field name>=<its value>' \
-F '<last field name>=<its value>' \
-F 'file=@cat.png;type=image/png'

Successful response​

201 — The new document with its upload URL and form fields.

{
"id": "3f1c2b7e-8d4a-4c1e-9b2f-6a7d5e4c3b21",
"meta": { "lastUpdated": "2026-10-09T09:12:44.318Z" },
"author": {
"reference": "Practitioner/8c5e7a21-4b9d-4f36-a1c8-0d2e6b9f3a54",
"display": "Alex Lee"
},
"fileName": "cat.png",
"contentType": "image/png",
"uploadOptions": {
"url": "https://storage.example.com/ovok-files",
"fields": {
"key": "binary/5d2a9c64-7e1b-4830-b6f5-9a3c1e8d7b02/8c5e7a21-4b9d-4f36-a1c8-0d2e6b9f3a54",
"<next field name>": "<its value>",
"<last field name>": "<its value>"
}
}
}
FieldTypeDescription
idstring (uuid)Document id. Use it in the other routes.
meta.lastUpdatedstringWhen the document last changed. ISO 8601.
authorobjectThe caller's profile. Left out when the caller has none.
author.referencestringProfile reference, for example Practitioner/<id>.
author.displaystringDisplay name of the caller.
fileNamestringThe file name you sent.
contentTypestringThe content type you sent.
publicTokenstringPublic token. Present only when isPublic was "true".
uploadOptions.urlstringURL to send the upload form to.
uploadOptions.fieldsobjectForm fields to send with the file. Each value is a string. Send every name and value unchanged. The names and the number of fields are not fixed, so the example shows placeholders for all but key.

Errors​

StatusMeaning
400The body fails validation: fileName is missing or empty, contentType is missing or not an allowed type, or isPublic is not the string "true" or "false". message lists each problem as path: message.
401Bearer token is missing, invalid or revoked.
403Your access policy does not allow creating the Binary or the DocumentReference.
404The new file has no storage location.
429You made more calls in the last minute than your user type allows.