Documentation

Dokko API — M2M Integration Guide

Machine-to-machine integration — authentication, repositories, files, and document processing.

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 call POST /admin/service-accounts with that token to mint a service account — the response gives you client_id and a one-time client_secret. Store the secret immediately; it cannot be retrieved later.
  • C. Exchange the credentials for a machine token: POST /auth/service/login with a form-encoded body (client_id + client_secret) and the X-Tenant header set to your organisation name. The response contains the access_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-sources returns it; copy the id, you’ll need it in step 3 when creating repositories.
  • 2. Create Permissions. POST /permissions for each team or access level. Save the returned ids.
  • 3. Create a Repository. POST /repositories with your document_source_id and the permission ids from step 2. The response includes the repository_id.
  • 4. Upload Files. POST /repositories/{repository_id}/items with multipart form data. The filename in the multipart header determines where the file is placed (e.g. filename=docs/report.pdf puts it in docs/).
  • 5. Trigger Ingestion. POST /document-sources/{document_source_id}/process kicks off ingestion so the uploaded files become searchable. Poll GET .../process/status until it reports COMPLETED.

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-Tenant header 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
email 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_secretstore 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 APIPUT /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 root
  • filename="docs/report.pdf" → file is placed in the docs/ folder
  • filename="docs/2024/report.pdf" → file is placed in docs/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.pdf not /docs/file.pdf
  • Do not include repository name: docs/file.pdf not repo-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 progress
  • COMPLETED — ingestion finished successfully
  • FAILED — ingestion encountered errors
  • CREATING_KNOWLEDGE_BASE — KB infrastructure is being set up
  • CREATING_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"

Get started

Read deep. Act fast.
On your documents.

The 14-day trial runs on your real library, not a sandbox. Bring your contracts, manuals, or frameworks — and see how Dokko reads them.