Skip to Content
We are live but in Staging 🎉
Conventions

API Conventions

Use this page as the baseline for all K3 API calls.

Transport and Endpoints

  • HTTP: https://k3.dev.dodil.io (staging) · https://k3.dodil.io (production)
  • gRPC: https://k3-grpc.dev.dodil.io (staging) · https://k3-grpc.dodil.io (production)
  • Examples in these docs use the staging HTTP URL. Switch to production by changing the host only — paths and headers are identical.

The HTTP API is the simplest way in — plain JSON over HTTPS — and is the default tab in these docs; every method is also available over gRPC (see Using gRPC). Export your token once and the examples work:

export DODIL_TOKEN="<your-token>"

Auth

Send one header on authenticated HTTP requests:

  • Authorization: Bearer <token>

That’s it. Your organization context is encoded in the bearer token’s claims — K3 derives it server-side, so you never send x-organization-id yourself. (For S3 byte-plane requests, you can alternatively authenticate with SigV4 using your Dodil service-account access key / secret — see Storage S3 Compatibility.)

Get a token with dodil login (interactive), or programmatically — apps and agents use the OAuth client-credentials flow. See Get an Access Token .

Using gRPC

Every method is also reachable over gRPC as dodil.k3.<pillar>.v1.<Service>/<Method> (e.g. dodil.k3.storage.v1.StorageService/ListBuckets). Install grpcurl (brew install grpcurl) and set the endpoint once:

export K3_GRPC="k3-grpc.dev.dodil.io:443" # staging; production: k3-grpc.dodil.io:443

Both endpoints are TLS by default — no -plaintext flag. grpcurl discovers the schema via server reflection, so no .proto is needed:

grpcurl -H "Authorization: Bearer $DODIL_TOKEN" $K3_GRPC list

If your endpoint doesn’t expose reflection, point grpcurl at the proto instead — grpcurl -proto k3_storage.proto -H "Authorization: Bearer $DODIL_TOKEN" $K3_GRPC ....

Field-name casing. gRPC request bodies use the proto field names — snake_case like organization_name, exactly as the .proto blocks in these docs show (grpcurl also accepts camelCase). Responses render in camelCase — that’s grpcurl’s default JSON output. The HTTP surface is camelCase both ways. So within a gRPC example: the request matches the proto block (snake_case), the response is camelCase.

Route Style

  • Bucket-scoped resources use /:bucket/...
  • Admin/global resources use /admin/...
  • IDs are usually opaque strings (source_id, pipeline_id, collection_id, rule_id, job_id)

Pagination Pattern

List RPCs commonly use cursor pagination:

  • Request: pagination.page_size, pagination.page_token
  • Response: pagination.next_page_token, pagination.total_count

Notes:

  • page_size=0 means server default (commonly 50).
  • total_count=-1 means unavailable or expensive to compute.

Optional Update Semantics

K3 uses wrappers for update requests to avoid ambiguity:

  • StringList and StringMap wrappers:
    • field absent: do not change
    • field present but empty: clear existing values
    • field present and non-empty: replace

For plain optional scalar fields:

  • unset: do not change
  • set (including empty string/zero): update to provided value

Compatibility and Runtime Notes

  1. Canonical vector search route is POST /:bucket/vector/search.
  2. Compatibility vector search route also exists: POST /:bucket/search/vector.
  3. Object routes in live router are key-in-path style:
    • GET /:bucket/objects/:key/info
    • DELETE /:bucket/objects/:key
    • GET /:bucket/objects/:key/url
  4. If proto annotation and runtime router differ, treat runtime router as source of truth.

Reusable cURL Template

export DODIL_TOKEN="<bearer_token>" curl -sS "https://k3.dev.dodil.io/<path>" \ -H "Authorization: Bearer $DODIL_TOKEN" \ -H "Content-Type: application/json"

See also