Base URL: https://new-app.dokko.ai
API prefix: all paths below are relative to https://new-app.dokko.ai/api/v1
Quick Start Guide
End-to-end flow, top to bottom. Steps A–C are one-time setup (done by your organisation admin — typically the same person doing the integration). Steps 1–5 are the API integration itself.
One-time setup
- A. You receive an email invitation (as an organisation admin) from your organization on Dokko. Open the link, set a password..
- B. Sign in via
POST /auth/login(or the web UI) to obtain an admin user token. Then callPOST /admin/service-accountswith that token to mint a service account — the response gives youclient_idand a one-timeclient_secret. Store the secret immediately; it cannot be retrieved later. - C. Exchange the credentials for a machine token:
POST /auth/service/loginwith a form-encoded body (client_id+client_secret) and theX-Tenantheader set to your organisation name. The response contains theaccess_token(Bearer JWT, 8-hour expiry, no refresh) used for every subsequent API call.
API integration
- 1. Get your Document Source ID. Each tenant has a single document source (the storage + retrieval bucket your content lives in), provisioned for you behind the scenes — you don’t configure it.
GET /document-sourcesreturns it; copy theid, you’ll need it in step 3 when creating repositories. - 2. Create Permissions.
POST /permissionsfor each team or access level. Save the returned ids. - 3. Create a Repository.
POST /repositorieswith yourdocument_source_idand the permission ids from step 2. The response includes therepository_id. - 4. Upload Files.
POST /repositories/{repository_id}/itemswith multipart form data. The filename in the multipart header determines where the file is placed (e.g.filename=docs/report.pdfputs it indocs/). - 5. Trigger Ingestion.
POST /document-sources/{document_source_id}/processkicks off ingestion so the uploaded files become searchable. PollGET .../process/statusuntil it reportsCOMPLETED.
The rest of this guide expands each step with the full request/response shape.
Onboarding & Authentication
The Dokko API uses JWT Bearer tokens for machine-to-machine authentication. Obtaining your first M2M token is a three-step setup performed once per integration; afterwards your application just re-runs Step C whenever its token is close to expiry.
There are two kinds of token involved:
- User access token — issued to a human (you, the organisation admin) by
POST /auth/login. Only used in Step B below, to mint service-account credentials. - M2M access token — issued to a service account by
POST /auth/service/login. Used by your application for every other call in this guide.
Token details (M2M)
- Algorithm: HS256
- Audience claim:
fastapi-m2m:auth - Subject claim: the service account’s UUID
- Expiry: 8 hours (28,800 seconds)
- No refresh token — re-authenticate before expiry by re-running Step C
- Header format:
Authorization: Bearer <access_token>
Since M2M tokens have no refresh mechanism, your application should either: (a) track the token’s issued time and proactively re-authenticate before the 8-hour window expires, or (b) catch 401 responses and re-authenticate on demand.
Authenticated requests carry the tenant identity in the token itself — no X-Tenant header is required after login. Only the user-login (/auth/login) and service-login (/auth/service/login) calls need the header, because they have no token yet.
Step A: Accept your invitation and sign in
Dokko sends an invitation email to the organisation admin’s address. The email contains:
- A link to set your password (which activates your account)
- Your organisation name — keep this; you’ll use it as the
X-Tenantheader value in every login call below
Once your account is active, obtain a user access token via POST /api/v1/auth/login.
Content-Type: application/x-www-form-urlencoded
Required Header
| Name | Description |
|---|---|
| X-Tenant | Organisation name or tenant UUID |
Form Fields
| Name | Type | Required | Description |
|---|---|---|---|
| string | Yes | Your email address | |
| password | string | Yes | Password you set when accepting the invitation |
Response (200 OK)
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer"
}
The web UI performs this login on your behalf — if you prefer, sign in there once and copy the access token out of the browser session for use in Step B.
Example
curl -X POST https://new-app.dokko.ai/api/v1/auth/login \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "X-Tenant: your-org-name" \
-d "email=admin@your-company.com" \
-d "password=<your-password>"
Step B: Create a service account
Use the user access token from Step A to mint a service account. The response contains a one-time client_secret — store it immediately, it is bcrypt-hashed at rest and cannot be retrieved later. If lost, use rotate-secret to issue a new one.
POST /api/v1/admin/service-accounts
Request Body (JSON)
| Name | Type | Required | Description |
|---|---|---|---|
| name | string (min 3) | Yes | Human-readable label for this service account |
Response (201 Created)
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"client_id": "sa_<opaque>",
"client_secret": "<cleartext — shown exactly once>",
"name": "production-integration"
}
Example
curl -X POST https://new-app.dokko.ai/api/v1/admin/service-accounts \
-H "Authorization: Bearer $USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "production-integration"}'
You now have everything you need for Step C: client_id, client_secret, and your organisation name (the same value you used for X-Tenant in Step A).
Step C: Exchange credentials for an M2M token
POST /api/v1/auth/service/login
OAuth2 client_credentials login (RFC 6749 §4.4.2). Authenticates the service account and returns a Bearer access token your application uses for all subsequent API calls.
Content-Type: application/x-www-form-urlencoded
Required Header
| Name | Description |
|---|---|
| X-Tenant | Organisation name or tenant UUID — same value you used in Step A |
Form Fields
| Name | Type | Required | Description |
|---|---|---|---|
| client_id | string | Yes | Service-account client identifier from Step B |
| client_secret | string | Yes | Service-account client secret from Step B |
Response (200 OK)
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer"
}
Error Responses
| Code | Meaning |
|---|---|
| 401 | Invalid client credentials |
| 404 | Tenant (organisation) not found |
| 500 | Internal server error |
Example
curl -X POST https://new-app.dokko.ai/api/v1/auth/service/login \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "X-Tenant: your-org-name" \
-d "client_id=sa_<opaque>" \
-d "client_secret=<opaque>"
Include the returned access_token as Authorization: Bearer <token> on every subsequent call.
Service account management (rotate / revoke / list)
These endpoints are gated by the organisation-admin role and require a user access token (Step A) — a service-account token cannot call them. Use them to inventory existing credentials, rotate a leaked secret, or revoke a credential set you no longer need.
GET /admin/service-accounts
GET /api/v1/admin/service-accounts
List service accounts for your tenant (paginated). Secrets are never included in this response.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| page_num | int | No | Page number (default: 1) |
| per_page | int | No | Items per page (default: 10, max: 100) |
Response (200 OK)
{
"items": [
{
"id": "uuid",
"client_id": "sa_<opaque>",
"name": "production-integration",
"is_active": true,
"created_at": "2026-06-01T10:30:00Z",
"last_login_at": "2026-06-02T08:15:00Z"
}
],
"has_next_page": false,
"page_number": 1,
"page_count": 1,
"page_size": 10,
"total_records": 1
}
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized — missing or invalid user token |
| 403 | Forbidden — caller is not an organisation admin |
| 500 | Internal server error |
Example
curl -X GET "https://new-app.dokko.ai/api/v1/admin/service-accounts?page_num=1&per_page=20" \
-H "Authorization: Bearer $USER_TOKEN"
GET /admin/service-accounts/{id}
GET /api/v1/admin/service-accounts/{service_account_id}
Fetch one service account by id.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| service_account_id | UUID | Yes | The service account’s id (the id returned by create / list) |
Response (200 OK)
{
"id": "uuid",
"client_id": "sa_<opaque>",
"name": "production-integration",
"is_active": true,
"created_at": "2026-06-01T10:30:00Z",
"last_login_at": "2026-06-02T08:15:00Z"
}
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden — caller is not an organisation admin |
| 404 | Service account not found |
| 500 | Internal server error |
Example
curl -X GET https://new-app.dokko.ai/api/v1/admin/service-accounts/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $USER_TOKEN"
DELETE /admin/service-accounts/{id}
DELETE /api/v1/admin/service-accounts/{service_account_id}
Revoke a service account. Returns 204 No Content. The account stops being able to authenticate immediately; tokens already issued to it remain valid until their 8-hour expiry. To force a hard cutover, rotate the secret instead — that takes effect immediately and keeps the same client_id.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| service_account_id | UUID | Yes | The service account to revoke |
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden — caller is not an organisation admin |
| 404 | Service account not found |
| 500 | Internal server error |
Example
curl -X DELETE https://new-app.dokko.ai/api/v1/admin/service-accounts/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $USER_TOKEN"
POST /admin/service-accounts/{id}/rotate-secret
POST /api/v1/admin/service-accounts/{service_account_id}/rotate-secret
Issue a fresh client_secret. The previous secret stops working immediately. The new cleartext secret is returned exactly once — same response shape as POST /admin/service-accounts. After rotation, re-run Step C with the new secret.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| service_account_id | UUID | Yes | The service account whose secret to rotate |
Request Body
None.
Response (200 OK)
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"client_id": "sa_<opaque>",
"client_secret": "<new cleartext — shown exactly once>",
"name": "production-integration"
}
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden — caller is not an organisation admin |
| 404 | Service account not found |
| 500 | Internal server error |
Example
curl -X POST https://new-app.dokko.ai/api/v1/admin/service-accounts/550e8400-e29b-41d4-a716-446655440000/rotate-secret \
-H "Authorization: Bearer $USER_TOKEN"
Common Patterns
Authorization Header
All API requests (except the login endpoint) require the Authorization header:
Authorization: Bearer <access_token>
Pagination
List endpoints return paginated results. Use these query parameters to control pagination:
| Name | Type | Required | Description |
|---|---|---|---|
| page_num | int | No | Page number (default: 1, minimum: 1) |
| per_page | int | No | Items per page (default: 10, min: 1, max: 100) |
Paginated Response Shape
{
"items": [ ... ],
"has_next_page": true,
"page_number": 1,
"page_count": 5,
"page_size": 10,
"total_records": 47
}
Error Responses
The API uses standard HTTP status codes:
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Resource created |
| 204 | Deleted (no content) |
| 207 | Multi-status (partial success for batch operations) |
| 400 | Bad request / validation error |
| 401 | Unauthorized — invalid or expired token |
| 402 | Payment required — subscription inactive |
| 404 | Resource not found |
| 422 | Unprocessable entity |
| 500 | Internal server error |
UUID Format
All resource IDs are UUIDs (e.g. 550e8400-e29b-41d4-a716-446655440000). Always use the full UUID string when referencing resources in path parameters or request bodies.
Permissions API
Permissions control access to repositories. Create named permissions and assign them to repositories to manage who can access which content.
List Permissions
GET /api/v1/permissions
Retrieve a paginated list of all permissions for your organisation.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| page_num | int | No | Page number (default: 1) |
| per_page | int | No | Items per page (default: 10, max: 100) |
Response (200 OK)
{
"items": [
{
"id": "uuid",
"name": "string",
"tenant_id": "uuid",
"created_at": "2024-01-15T10:30:00Z"
}
],
"has_next_page": false,
"page_number": 1,
"page_count": 1,
"page_size": 10,
"total_records": 3
}
Example
curl -X GET "https://new-app.dokko.ai/api/v1/permissions?page_num=1&per_page=20" \
-H "Authorization: Bearer $TOKEN"
Create Permission
POST /api/v1/permissions
Request Body (JSON)
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Name of the permission |
Response (201 Created)
{
"id": "uuid",
"name": "engineering-team",
"tenant_id": "uuid",
"created_at": "2024-01-15T10:30:00Z"
}
Example
curl -X POST https://new-app.dokko.ai/api/v1/permissions \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "engineering-team"}'
Get Permission by ID
GET /api/v1/permissions/{id}
Retrieve a single permission by its ID.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | UUID | Yes | Permission ID |
Response (200 OK)
{
"id": "uuid",
"name": "engineering-team",
"tenant_id": "uuid",
"created_at": "2024-01-15T10:30:00Z"
}
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 404 | Permission not found |
| 500 | Internal server error |
Example
curl -X GET https://new-app.dokko.ai/api/v1/permissions/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $TOKEN"
Update Permission
PATCH /api/v1/permissions/{id}
Rename a permission. The permission’s repository mappings are preserved.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | UUID | Yes | Permission ID |
Request Body (JSON)
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | New name |
Response (200 OK)
{
"id": "uuid",
"name": "engineering-team-renamed",
"tenant_id": "uuid",
"created_at": "2024-01-15T10:30:00Z"
}
Error Responses
| Code | Meaning |
|---|---|
| 400 | Validation error |
| 401 | Unauthorized |
| 404 | Permission not found |
| 422 | Unprocessable entity (malformed body) |
| 500 | Internal server error |
Example
curl -X PATCH https://new-app.dokko.ai/api/v1/permissions/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "engineering-team-renamed"}'
Delete Permission
DELETE /api/v1/permissions/{id}
Deletes a permission and its associated repository mappings. Returns 204 No Content. Any repositories that referenced this permission lose it from their permission list.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | UUID | Yes | Permission ID |
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 404 | Permission not found |
| 500 | Internal server error |
Example
curl -X DELETE https://new-app.dokko.ai/api/v1/permissions/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $TOKEN"
Document Sources API
Each tenant has a single document source (the storage + retrieval bucket your content lives in), provisioned for you behind the scenes. You don’t create it, configure it, or attach a knowledge base to it — that’s all done for you. You only need its id so you can pass it as document_source_id when creating repositories.
List Document Sources
GET /api/v1/document-sources
Returns the document source(s) for your tenant. In practice you will see exactly one — copy its id and save it; that’s the document_source_id you’ll use for everything below.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| page_num | int | No | Page number (default: 1) |
| per_page | int | No | Items per page (default: 10, max: 100) |
Response (200 OK)
{
"items": [
{
"id": "uuid",
"type": "S3",
"identifier": "tenant-bucket-name",
"tenant_id": "uuid",
"status": "unlocked",
"is_locked": false
}
],
"has_next_page": false,
"page_number": 1,
"page_count": 1,
"page_size": 10,
"total_records": 1
}
Example
curl -X GET https://new-app.dokko.ai/api/v1/document-sources \
-H "Authorization: Bearer $TOKEN"
Get Document Source by ID
GET /api/v1/document-sources/{document_source_id}
Retrieve full details of a single document source, including its (pre-provisioned) Bedrock KB configuration.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| document_source_id | UUID | Yes | Document source ID (from the list endpoint) |
Response (200 OK)
{
"id": "uuid",
"type": "S3",
"identifier": "my-bucket-name",
"tenant_id": "uuid",
"status": "unlocked",
"is_locked": false,
"llm_chat_configuration": {
"id": "uuid",
"name": "default",
"tenant_id": "uuid",
"llm_provider": "openai",
"created_at": "2024-01-15T10:30:00Z",
"model_name": "gpt-4o"
},
"agent": null,
"bedrock_knowledge_base_id": "ABC123",
"bedrock_data_source_id": "DS456",
"bedrock_embedding_model": "TITAN_TEXT_V2",
"bedrock_parser_strategy": "default",
"bedrock_parsing_prompt": null,
"bedrock_fm_model_arn": null,
"bedrock_chunking_strategy": "fixed_size"
}
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 404 | Document source not found |
| 500 | Internal server error |
Example
curl -X GET https://new-app.dokko.ai/api/v1/document-sources/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $TOKEN"
Get Document Source Folder Structure
GET /api/v1/document-sources/{document_source_id}/folder-structure
Retrieve the hierarchical file and folder structure of a document source — every file across every repository inside it. Useful for browsing or for confirming uploads landed where you expect.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| document_source_id | UUID | Yes | Document source ID |
Response (200 OK)
{
"folders": {
"docs": {
"folders": {},
"files": {
"guide.pdf": {
"key": "docs/guide.pdf",
"filename": "guide.pdf",
"size": 102400,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"bucket_name": "my-bucket"
}
},
"repository": {},
"is_locked": false
}
},
"files": {},
"repository": {},
"is_locked": false
}
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 404 | Document source not found |
| 500 | Internal server error |
Example
curl -X GET https://new-app.dokko.ai/api/v1/document-sources/550e8400-e29b-41d4-a716-446655440000/folder-structure \
-H "Authorization: Bearer $TOKEN"
Repositories API
Repositories are logical groupings of documents within a document source. Each repository belongs to exactly one document source and can have permissions assigned to it.
Create Repository
POST /api/v1/repositories
Create a new repository within a document source.
Request Body (JSON)
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Repository name |
| document_source_id | UUID | Yes | ID of the parent document source |
| type | string | No | Repository type (e.g. "semantic") |
| permission_ids | UUID[] | No | Array of permission IDs to assign |
Response (201 Created)
{
"id": "uuid",
"name": "my-repository",
"created_at": "2024-01-15T10:30:00Z",
"type": "semantic",
"processing_started_at": null,
"processing_ended_at": null,
"llm_chat_configuration": null,
"agent_id": null
}
Error Responses
| Code | Meaning |
|---|---|
| 400 | Validation error |
| 401 | Unauthorized |
| 404 | Referenced document source or permission not found |
| 422 | Unprocessable entity (malformed body) |
| 500 | Internal server error |
Example
curl -X POST https://new-app.dokko.ai/api/v1/repositories \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-repository",
"document_source_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "semantic",
"permission_ids": ["aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"]
}'
List Repositories
GET /api/v1/repositories
Retrieve a paginated list of repositories. You must provide either document_source_id or set only_web_search_repos=true.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| document_source_id | UUID | Cond. | Required unless only_web_search_repos=true |
| only_web_search_repos | bool | No | If true, return only web-search repositories (default: false) |
| page_num | int | No | Page number (default: 1) |
| per_page | int | No | Items per page (default: 10, max: 100) |
Response (200 OK)
{
"items": [
{
"id": "uuid",
"name": "my-repository",
"tenant_id": "uuid",
"document_source_id": "uuid",
"created_at": "2024-01-15T10:30:00Z",
"type": "semantic",
"processing_started_at": null,
"processing_ended_at": null
}
],
"has_next_page": false,
"page_number": 1,
"page_count": 1,
"page_size": 10,
"total_records": 1
}
Error Responses
| Code | Meaning |
|---|---|
| 400 | Missing required document_source_id (and only_web_search_repos is false) |
| 401 | Unauthorized |
| 500 | Internal server error |
Example
curl -X GET "https://new-app.dokko.ai/api/v1/repositories?document_source_id=550e8400-e29b-41d4-a716-446655440000&page_num=1&per_page=20" \
-H "Authorization: Bearer $TOKEN"
Get Repository by ID
GET /api/v1/repositories/{repository_id}
Retrieve a single repository by its ID.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| repository_id | UUID | Yes | Repository ID |
Response (200 OK)
{
"id": "uuid",
"name": "my-repository",
"created_at": "2024-01-15T10:30:00Z",
"type": "semantic",
"processing_started_at": null,
"processing_ended_at": null,
"llm_chat_configuration": {
"id": "uuid",
"name": "default",
"temperature": 0.7,
"max_tokens": 4096,
"tenant_id": "uuid",
"is_read_only": false
},
"agent_id": null
}
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 404 | Repository not found |
| 500 | Internal server error |
Example
curl -X GET https://new-app.dokko.ai/api/v1/repositories/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $TOKEN"
Update Repository
PATCH /api/v1/repositories/{repository_id}
Update a repository’s name, type, or permissions.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| repository_id | UUID | Yes | Repository ID |
Request Body (JSON) — all fields optional
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | No | New repository name |
| type | string | No | Repository type |
| permission_ids | UUID[] | No | New set of permission IDs (replaces the existing set) |
Response (200 OK) — same shape as GET /repositories/{repository_id}
Error Responses
| Code | Meaning |
|---|---|
| 400 | Validation error |
| 401 | Unauthorized |
| 404 | Repository not found, or referenced permission not found |
| 422 | Unprocessable entity (malformed body) |
| 500 | Internal server error |
Example
curl -X PATCH https://new-app.dokko.ai/api/v1/repositories/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "renamed-repo", "permission_ids": ["perm-uuid-1", "perm-uuid-2"]}'
Delete Repository
DELETE /api/v1/repositories/{repository_id}
Delete a repository and all of its files. Returns 204 No Content. The repository is also removed from any permission mappings; the parent document source is not affected.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| repository_id | UUID | Yes | Repository ID |
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 404 | Repository not found |
| 500 | Internal server error |
Example
curl -X DELETE https://new-app.dokko.ai/api/v1/repositories/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $TOKEN"
Repository Files API
These endpoints manage files and folders within a repository. All paths are relative to the repository root — do not include the repository name or leading slashes in file paths.
Get Repository File Tree
GET /api/v1/repositories/{repository_id}/items
Retrieve the hierarchical file and folder structure of a repository.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| repository_id | UUID | Yes | Repository ID |
Response (200 OK)
{
"folders": {
"reports": {
"folders": {},
"files": {
"q4-report.pdf": {
"name": "q4-report.pdf",
"ext": "pdf",
"last_modified": "2024-01-15T10:30:00Z",
"key": "reports/q4-report.pdf",
"is_locked": false,
"e_tag": "abc123",
"size": 204800,
"version_id": "v1"
}
},
"repository": {},
"is_locked": false
}
},
"files": {},
"repository": {},
"is_locked": false
}
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 404 | Repository not found |
| 500 | Internal server error |
Example
curl -X GET https://new-app.dokko.ai/api/v1/repositories/550e8400-e29b-41d4-a716-446655440000/items \
-H "Authorization: Bearer $TOKEN"
Upload Files and Create Folders
POST /api/v1/repositories/{repository_id}/items
Upload files and/or create folders in a repository. Uses multipart form data.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| repository_id | UUID | Yes | Repository ID |
Request Body (multipart/form-data)
| Name | Type | Required | Description |
|---|---|---|---|
| files | File[] | No | One or more files to upload |
| folders | string (JSON) | No | JSON array of folder paths to create, e.g. '["docs", "assets/images"]' |
To attach filter metadata to a file, do it after upload via the Files API —
PUT /files/{file_id}/metadata. Keeps the upload call simple and the metadata flow uniform whether the file was just uploaded or already existed.
File Placement via Filename (Important)
The filename in the multipart Content-Disposition header determines where the file is placed within the repository. To upload a file into a subfolder, include the path in the filename.
filename="report.pdf"→ file is placed at the repository rootfilename="docs/report.pdf"→ file is placed in thedocs/folderfilename="docs/2024/report.pdf"→ file is placed indocs/2024/
In curl, use the ;filename= syntax to set a custom path: -F "files=@local-file.pdf;filename=docs/report.pdf"
Response (200 OK or 207 Multi-Status)
{
"succeeded": [
{ "identifier": "docs/report.pdf", "display_name": "report.pdf" }
],
"failed": [
{
"identifier": "bad-file.exe",
"display_name": "bad-file.exe",
"message": "Unsupported file type",
"code": "INVALID_TYPE"
}
],
"result": { "folders": {}, "files": {} },
"status": "success",
"total_succeeded": 1,
"total_failed": 0
}
Status is "success" (all OK), "partial" (some failed), or "failure" (all failed). HTTP status is 200 for success, 207 for partial, 500 for total failure.
Examples
Upload to repository root:
curl -X POST https://new-app.dokko.ai/api/v1/repositories/550e8400-...-440000/items \
-H "Authorization: Bearer $TOKEN" \
-F "files=@/path/to/document.pdf" \
-F 'folders=[]'
Upload into a subfolder:
curl -X POST https://new-app.dokko.ai/api/v1/repositories/550e8400-...-440000/items \
-H "Authorization: Bearer $TOKEN" \
-F "files=@report.pdf;filename=docs/2024/report.pdf" \
-F 'folders=[]'
Create folders:
curl -X POST https://new-app.dokko.ai/api/v1/repositories/550e8400-...-440000/items \
-H "Authorization: Bearer $TOKEN" \
-F 'folders=["reports", "reports/2024"]'
Delete Files and Folders
DELETE /api/v1/repositories/{repository_id}/items
Delete one or more files and/or folders from a repository.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| repository_id | UUID | Yes | Repository ID |
Request Body (JSON)
| Name | Type | Required | Description |
|---|---|---|---|
| items | array | Yes | Array of items to delete. Each item is either a string (file path) or an object {"path": "...", "type": "file"|"folder"} |
Path Format Notes
- Paths are relative to repository root
- Do not include leading slashes:
docs/file.pdfnot/docs/file.pdf - Do not include repository name:
docs/file.pdfnotrepo-name/docs/file.pdf
Response (200 OK or 207 Multi-Status) — same shape as upload response.
Example
curl -X DELETE https://new-app.dokko.ai/api/v1/repositories/550e8400-...-440000/items \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"items": ["docs/old-report.pdf", {"path": "temp", "type": "folder"}]
}'
Update Files and Folders (Move / Rename / Replace)
PATCH /api/v1/repositories/{repository_id}/items
Move, rename, or replace file content. Uses multipart form data. Operations are processed in order: moves first, then content updates.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| repository_id | UUID | Yes | Repository ID |
Request Body (multipart/form-data)
| Name | Type | Required | Description |
|---|---|---|---|
| operations | string (JSON) | Yes | JSON object describing the operations (schema below) |
| files | File[] | No | New file content for content-update operations |
Operations JSON schema
{
"items": [
{
"path": "old/path/file.pdf",
"type": "file",
"new_path": "new/path/file.pdf"
}
]
}
Response (200 OK or 207 Multi-Status) — same shape as upload response.
Example — rename a file
curl -X PATCH https://new-app.dokko.ai/api/v1/repositories/550e8400-...-440000/items \
-H "Authorization: Bearer $TOKEN" \
-F 'operations={"items": [{"path": "docs/old-name.pdf", "type": "file", "new_path": "docs/new-name.pdf"}]}'
Example — update file content
To replace the content of an existing file, include the file’s current path in the operations JSON (without new_path) and attach the new file with a filename that matches the path in the operation. The filename in the multipart upload is used to match the file to its operation.
curl -X PATCH https://new-app.dokko.ai/api/v1/repositories/550e8400-...-440000/items \
-H "Authorization: Bearer $TOKEN" \
-F 'operations={"items": [{"path": "docs/report.pdf", "type": "file"}]}' \
-F "files=@/local/path/to/updated-report.pdf;filename=docs/report.pdf"
Get File Content / Download
POST /api/v1/repositories/{repository_id}/items/content
Retrieve the content of a file. By default returns a JSON envelope containing a presigned S3 download URL; pass direct=true to stream the file body through the API instead.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| repository_id | UUID | Yes | Repository ID |
Request Body (JSON)
| Name | Type | Required | Description |
|---|---|---|---|
| path | string | Yes | Relative file path within the repository |
| as_attachment | bool | No | If true (default), download as attachment; if false, inline |
| direct | bool | No | If true, stream the file content through the API; if false (default), return a presigned download URL |
Response (200 OK) — default (presigned URL)
{
"url": "https://<s3-presigned-url>"
}
Follow the URL to download the file. The URL is short-lived; do not cache it.
Response (200 OK) — direct=true
The response body is the raw file content, with Content-Type reflecting the file’s media type and Content-Disposition set to attachment (or inline if as_attachment=false).
Example — get presigned URL
curl -X POST https://new-app.dokko.ai/api/v1/repositories/550e8400-...-440000/items/content \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"path": "docs/report.pdf", "as_attachment": true}'
Example — stream directly
curl -X POST https://new-app.dokko.ai/api/v1/repositories/550e8400-...-440000/items/content \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"path": "docs/report.pdf", "as_attachment": true, "direct": true}' \
-o report.pdf
Files API
These endpoints operate on a single file by its file_id — the UUID assigned when the file was uploaded (you’ll find it on file objects returned by the Repository File Tree and search results).
The metadata endpoints below manage filter metadata — user-defined key/value pairs (e.g. team, region, is_public) that you attach to files so retrieval can filter on them later. Reserved keys (such as repository_id) are managed by the system and cannot be overwritten through these endpoints.
Download a File
GET /api/v1/files/{file_id}
Returns a 307 Temporary Redirect whose Location header points at a presigned S3 download URL. Follow the redirect to download the file (in curl, pass -L).
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| file_id | UUID | Yes | The file’s id |
Response (307 Temporary Redirect)
Location: https://<s3-presigned-url>
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 404 | File not found |
| 500 | Failed to download file |
Example
curl -L -X GET https://new-app.dokko.ai/api/v1/files/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $TOKEN" \
-o downloaded-file
Get File Metadata
GET /api/v1/files/{file_id}/metadata
Retrieve the filter metadata currently attached to a file.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| file_id | UUID | Yes | The file’s id |
Response (200 OK)
{
"file_id": "550e8400-e29b-41d4-a716-446655440000",
"metadata": {
"team": "engineering",
"region": "eu",
"is_public": false,
"tags": ["q4", "internal"]
}
}
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 404 | Filter metadata not found for this file |
| 500 | Internal server error |
Example
curl -X GET https://new-app.dokko.ai/api/v1/files/550e8400-e29b-41d4-a716-446655440000/metadata \
-H "Authorization: Bearer $TOKEN"
Update File Metadata
PUT /api/v1/files/{file_id}/metadata
Replace the user-defined filter metadata fields on a file. Reserved/system fields (e.g. repository_id) are preserved automatically — do not include them in the request body.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| file_id | UUID | Yes | The file’s id |
Request Body (JSON)
| Name | Type | Required | Description |
|---|---|---|---|
| metadata | object | Yes | Mapping of user-defined keys to values. Values may be string, bool, int, or list[string]. |
Response (200 OK) — same shape as GET /files/{file_id}/metadata.
Error Responses
| Code | Meaning |
|---|---|
| 400 | Validation error (e.g. attempted to set a reserved key, or an unsupported value type) |
| 401 | Unauthorized |
| 404 | Filter metadata not found for this file |
| 500 | Internal server error |
Example
curl -X PUT https://new-app.dokko.ai/api/v1/files/550e8400-e29b-41d4-a716-446655440000/metadata \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"metadata": {
"team": "engineering",
"region": "eu",
"is_public": false,
"tags": ["q4", "internal"]
}
}'
Reset File Metadata
POST /api/v1/files/{file_id}/metadata/reset
Clears all user-defined filter-metadata fields on a file. System-managed fields (e.g. repository_id) are kept. Returns the file’s metadata after the reset.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| file_id | UUID | Yes | The file’s id |
Request Body
None.
Response (200 OK) — same shape as GET /files/{file_id}/metadata, with only the system fields populated.
Error Responses
| Code | Meaning |
|---|---|
| 401 | Unauthorized |
| 404 | Filter metadata not found for this file |
| 500 | Internal server error |
Example
curl -X POST https://new-app.dokko.ai/api/v1/files/550e8400-e29b-41d4-a716-446655440000/metadata/reset \
-H "Authorization: Bearer $TOKEN"
Document Processing API
These endpoints trigger and monitor document ingestion (processing) for a document source. Once processing is run, the documents become searchable.
Start Processing
POST /api/v1/document-sources/{document_source_id}/process
Start an ingestion job for a document source — uploaded files become searchable once it completes. Returns 202 Accepted; poll /process/status to track progress.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| document_source_id | UUID | Yes | Document source ID |
Request Body
None.
Response (202 Accepted)
{
"status": "RUNNING",
"statistics": {
"numberOfDocumentsScanned": 0,
"numberOfNewDocumentsIndexed": 0,
"numberOfModifiedDocumentsIndexed": 0,
"numberOfDocumentsDeleted": 0,
"numberOfDocumentsFailed": 0
},
"startedAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
Error Responses
| Code | Meaning |
|---|---|
| 400 | Document source does not have Bedrock KB configured |
| 401 | Unauthorized |
| 404 | Document source not found |
| 409 | An ingestion job is already running |
| 500 | Internal server error |
Example
curl -X POST https://new-app.dokko.ai/api/v1/document-sources/550e8400-e29b-41d4-a716-446655440000/process \
-H "Authorization: Bearer $TOKEN"
Get Processing Status
GET /api/v1/document-sources/{document_source_id}/process/status
Check the status of the current or most recent ingestion job for a document source.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| document_source_id | UUID | Yes | Document source ID |
Response (200 OK)
{
"status": "COMPLETED",
"statistics": {
"numberOfDocumentsScanned": 15,
"numberOfNewDocumentsIndexed": 12,
"numberOfModifiedDocumentsIndexed": 3,
"numberOfDocumentsDeleted": 0,
"numberOfDocumentsFailed": 0
},
"startedAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:35:00Z"
}
Possible status values
RUNNING— ingestion is in progressCOMPLETED— ingestion finished successfullyFAILED— ingestion encountered errorsCREATING_KNOWLEDGE_BASE— KB infrastructure is being set upCREATING_DATA_SOURCE— data source is being configured
Error Responses
| Code | Meaning |
|---|---|
| 400 | No active ingestion job found |
| 401 | Unauthorized |
| 500 | Internal server error |
Example
curl -X GET https://new-app.dokko.ai/api/v1/document-sources/550e8400-e29b-41d4-a716-446655440000/process/status \
-H "Authorization: Bearer $TOKEN"