Files
Operations tagged Files in the public API.
About Files
A file is a document you upload with POST /files to turn it into knowledge with POST /knowledge (name and file_id). Uploading stores it and emits file.created; it trains nothing until a dataset is created from it. Accepted: txt, pdf, doc, docx, rtf and odt documents, png, jpg, jpeg and webp images (read by OCR, as are scanned PDFs) and xlsx, xls, csv and ods spreadsheets — at most 10 MB each, and 20 files or 90 MB per batch, by default. The content must match the extension.
A file backs at most one dataset (knowledge_dataset_id): naming it in a second POST /knowledge is 409 FILE_ALREADY_ATTACHED. While it backs one it cannot be deleted (409 FILE_BACKS_DATASET): delete the dataset instead, which deletes its file with it.
IDs you will meet.
id— the file id, an integer: thefile_idPOST /knowledgetakes.file_idon the file object — a UUID, informational only.knowledge_dataset_id— the dataset made from the file.
IDs on this page
- File id
<FILE_ID> - Integer: the file's
id. The UUID in itsfile_idfield is not accepted here.Get it from
- POST /v1/files returns it as
id - POST /v1/files returns it as
data[].id - GET /v1/files returns it as
data[].id - Webhook file.created carries it as
data.object.id
- POST /v1/files returns it as
List files
POST /files and those behind datasets created from the dashboard or a cloud import. knowledge_dataset_id is set on each file that backs a dataset.- Required scope
- files:read
- Idempotency
- Read-only
- Rate limits
Query parameters
limitintegerOptionalPage size, clamped to 1–100.Default:
20Minimum:1Maximum:100starting_afterstringOptionalCursor from a previous page'snext_cursor: returns the page after it. A cursor minted for another list,sortororderis 422INVALID_CURSOR.ending_beforestringOptionalCursor from a previous page'sprevious_cursor: returns the page before it. Wins when both cursors are sent.created[gte]stringOptionalOnly rows created on or after this instant:YYYY-MM-DD(whole UTC day) or an RFC 3339 timestamp with a zone. Anything else is 422INVALID_PARAMETER.created[lte]stringOptionalOnly rows created on or before this instant:YYYY-MM-DD(whole UTC day) or an RFC 3339 timestamp with a zone. Anything else is 422INVALID_PARAMETER.
Responses
- 200Success.
objectstringRequiredAlways
listdataarray of FileResourceRequiredhas_morebooleanRequirednext_cursorstringnullableRequiredprevious_cursorstringnullableRequiredurlstringRequiredAlways
/v1/files
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither.Error codesACCOUNT_SELECTOR_NOT_SUPPORTED
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 422Validation failed. See
error.details.Error codesINVALID_CURSORINVALID_PARAMETER
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X GET 'https://api.agentency.com/v1/files' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "list",
"data": [
{
"object": "file",
"id": 1,
"file_id": "0b6f2f4e-8a71-4c55-9d1e-3c2a7b9e5f10",
"filename": "refund-policy.pdf",
"mime_type": "application/pdf",
"extension": "pdf",
"size_bytes": 48213,
"status": "uploaded",
"knowledge_dataset_id": 1,
"created_at": "2026-01-01T00:00:00+00:00"
}
],
"has_more": false,
"next_cursor": null,
"previous_cursor": null,
"url": "/v1/files"
}Upload one or more files
id to POST /knowledge as file_id. Uploading trains nothing by itself, and each file emits file.created. Send a single file — answered with a file object — or a files[] batch, answered with a list; a batch is stored all or nothing, under one Idempotency-Key.
The type is checked by extension and by content (a binary renamed .txt is 422 VALIDATION_FAILED); the size and batch limits are on the fields.- Required scope
- files:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- file.created
- Rate limits
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Request body
POST /v1/files.
Accepts either a single file or a files[] batch. The dashboard has
always had a multi-file upload; the API forced one request per file, so
importing a folder of PDFs meant N round trips, N idempotency keys, and no
way to treat the import as one unit.filestringOptionalOne file:txt,pdf,doc,docx,rtf,odt,png,jpg,jpeg,webp,xlsx,xls,csvorods, at most 10 MB by default. Its content must match its extension (a binary renamed.txtis 422). Send this orfiles[]; when both are sent onlyfileis stored.Format:
binaryfilesarray of stringOptionalA batch of files with the same type and size rules: at most 20 files and 90 MB together by default. The batch is stored all or nothing, and oneIdempotency-Keycovers it.Min items:
1Max items:20
Responses
- 201
FileResourceany of
Shape 1object
objectstringRequiredAlways
listdataarray of FileResourceRequiredhas_morebooleanRequirednext_cursoranynullableRequiredprevious_cursoranynullableRequiredurlstringRequiredAlways
/v1/files
Shape 2FileResource
objectstringRequiredAlways
fileidintegerRequiredThe file id. Pass it asfile_idtoPOST /knowledge.file_idstringRequiredThe file's UUID. Informational: every/v1operation takes the integerid.filenamestringRequiredThe name the file was uploaded with.mime_typestringRequiredThe MIME type detected from the file's content.extensionstringRequiredThe lower-case extension of the uploaded name, without the dot;binwhen the name has none.size_bytesintegerRequiredSize in bytes.statusstringRequireduploaded(stored),processing,processed,failedorarchived(replaced byPOST /knowledge/{id}/replace_file).Possible values
uploadedprocessingprocessedfailedarchivedknowledge_dataset_idintegernullableRequiredThe knowledge dataset created from this file;nullwhile the file backs none. A file backs at most one dataset.created_atstringnullableRequiredWhen the file was uploaded (ISO 8601, UTC).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 409The request conflicts with the current resource state.
Error codesIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSEDVALIDATION_FAILED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X POST 'https://api.agentency.com/v1/files' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"
-d '{
"file": "file",
"files": []
}'Response
Example 201 response
{
"object": "file",
"id": 1,
"file_id": "0b6f2f4e-8a71-4c55-9d1e-3c2a7b9e5f10",
"filename": "price-list.txt",
"mime_type": "text/plain",
"extension": "txt",
"size_bytes": 56,
"status": "uploaded",
"knowledge_dataset_id": null,
"created_at": "2026-01-01T00:00:00+00:00"
}Retrieve a file
knowledge_dataset_id). /v1 does not return the file's bytes.- Required scope
- files:read
- Idempotency
- Read-only
- Rate limits
Integer: the file'sid(path)File idid. The UUID in itsfile_idfield is not accepted here.Placeholder in the samples:
<FILE_ID>Get it from
- POST /v1/files returns it as
id - POST /v1/files returns it as
data[].id - GET /v1/files returns it as
data[].id - Webhook file.created carries it as
data.object.id
- POST /v1/files returns it as
Path parameters
idintegerRequiredThe file id.
Responses
- 200
FileResourceobjectstringRequiredAlways
fileidintegerRequiredThe file id. Pass it asfile_idtoPOST /knowledge.file_idstringRequiredThe file's UUID. Informational: every/v1operation takes the integerid.filenamestringRequiredThe name the file was uploaded with.mime_typestringRequiredThe MIME type detected from the file's content.extensionstringRequiredThe lower-case extension of the uploaded name, without the dot;binwhen the name has none.size_bytesintegerRequiredSize in bytes.statusstringRequireduploaded(stored),processing,processed,failedorarchived(replaced byPOST /knowledge/{id}/replace_file).Possible values
uploadedprocessingprocessedfailedarchivedknowledge_dataset_idintegernullableRequiredThe knowledge dataset created from this file;nullwhile the file backs none. A file backs at most one dataset.created_atstringnullableRequiredWhen the file was uploaded (ISO 8601, UTC).
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither.Error codesACCOUNT_SELECTOR_NOT_SUPPORTED
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X GET 'https://api.agentency.com/v1/files/<FILE_ID>' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "file",
"id": 1,
"file_id": "0b6f2f4e-8a71-4c55-9d1e-3c2a7b9e5f10",
"filename": "refund-policy.pdf",
"mime_type": "application/pdf",
"extension": "pdf",
"size_bytes": 48213,
"status": "uploaded",
"knowledge_dataset_id": 1,
"created_at": "2026-01-01T00:00:00+00:00"
}Delete a file
file.deleted. A file that still backs a knowledge dataset is 409 FILE_BACKS_DATASET (details.dataset_id), and nothing changes: delete that dataset instead (DELETE /knowledge/{id}), which deletes its file with it.- Required scope
- files:write
- Idempotency
- Accepts Idempotency-Key
- Webhook events
- file.deleted
- Rate limits
Integer: the file'sid(path)File idid. The UUID in itsfile_idfield is not accepted here.Placeholder in the samples:
<FILE_ID>Get it from
- POST /v1/files returns it as
id - POST /v1/files returns it as
data[].id - GET /v1/files returns it as
data[].id - Webhook file.created carries it as
data.object.id
- POST /v1/files returns it as
Path parameters
idintegerRequiredThe file id.
Header parameters
Idempotency-KeystringOptionalMakes a retry safe. The first 2xx answer is stored for 24 h and replayed for the same key withIdempotency-Replayed: true; a retry while the first request runs is 409IDEMPOTENCY_IN_FLIGHT; the same key with a different payload is 422IDEMPOTENCY_KEY_REUSED; a malformed key is 400INVALID_IDEMPOTENCY_KEY.Min length:
16Max length:128Pattern:^[A-Za-z0-9_-]+$
Responses
- 200Success.
objectstringRequiredAlways
fileidintegerRequiredThe file id.deletedbooleanRequiredAlwaystrue.
- 400A tenant selector header named a tenant other than the API key's own (
ACCOUNT_SELECTOR_NOT_SUPPORTED): an all-digitX-Account-Idother than the key owner's id or, whileworkspaces.context_enabledis on, anX-Workspace-Idother than the key's workspace (ws_prefix optional, case-insensitive). A header naming the key's own tenant, or a non-numericX-Account-Id, is ignored; a key cannot switch tenants, so send neither. A mutation that honoursIdempotency-Keyalso returnsINVALID_IDEMPOTENCY_KEYwhen that header is not 16–128[A-Za-z0-9_-]characters.Error codesACCOUNT_SELECTOR_NOT_SUPPORTEDINVALID_IDEMPOTENCY_KEY
- 401Missing or invalid API key.
Error codesUNAUTHENTICATED
- 403The API key is missing a required scope.
Error codesACCOUNT_SUSPENDEDINSUFFICIENT_SCOPE
- 404The resource does not exist on this account.
Error codesNOT_FOUND
- 409The request conflicts with the current resource state.
Error codesFILE_BACKS_DATASETIDEMPOTENCY_IN_FLIGHT
- 422Validation failed. See
error.details.Error codesIDEMPOTENCY_KEY_REUSED
- 429Rate limited. Honour the Retry-After header before retrying.
Error codesRATE_LIMITED
- 500Unexpected server error. Retry with the same Idempotency-Key.
Error codesSERVER_ERROR
Request
curl -X DELETE 'https://api.agentency.com/v1/files/<FILE_ID>' \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json"Response
Example 200 response
{
"object": "file",
"id": 1,
"deleted": true
}