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:443Both 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 listIf 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=0means server default (commonly 50).total_count=-1means unavailable or expensive to compute.
Optional Update Semantics
K3 uses wrappers for update requests to avoid ambiguity:
StringListandStringMapwrappers:- 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
- Canonical vector search route is
POST /:bucket/vector/search. - Compatibility vector search route also exists:
POST /:bucket/search/vector. - Object routes in live router are key-in-path style:
GET /:bucket/objects/:key/infoDELETE /:bucket/objects/:keyGET /:bucket/objects/:key/url
- 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"