Pipelines — API Reference
The Pipelines domain spans three gRPC services across three proto packages:
| Service | Package | Owns |
|---|---|---|
| SourceService | dodil.data.source.v1 | Sources (external data sources + the auto-created internal S3 source) and Credentials (OAuth / API keys / PATs / access keys) |
| PipelineService | dodil.data.pipeline.v1 | Pipelines and their destinations (the three facet creators + CRUD), Template catalog browsing, and pipeline-chain teardown |
| IngestService | dodil.data.ingest.v1 | Ingest rules (triggers), source sync (Discovery / Ingestion / SyncStatus), and ingest jobs (per-object runs) |
PipelineService is the centre of the platform. The pillar split collapsed three route trees — /:bucket/vector/…, /:bucket/tables/pipelines and /:bucket/objects/destinations — into pipeline facets, so creating a vector collection, a pipeline-written table, or an object destination are all one shape now. Pipelines is the canonical definition; the Vector and SQL sections point here.
For the typed domain model (Source, Credential, Pipeline, Template, IngestRule, IngestJob) see Core Concepts. For headers and error envelope see Conventions.
Creating a pipeline does not start ingestion. No facet creator writes an ingest rule — binding one is a separate, mandatory step. This is the single most common way to end up with a collection or table that looks correct and never receives an object. See Rules.
Sections
- Sources —
CreateSource·GetSource·ListSources·UpdateSource·DeleteSource - Credentials —
StoreCredential·ListCredentials·DeleteCredential· OAuth flow (GetOAuthUrl·ExchangeOAuthCode·RefreshOAuthToken) - Pipelines —
CreateVectorPipeline·CreateTablePipeline·CreateObjectPipeline·CreatePipeline·GetPipeline·ListPipelines·UpdatePipeline·DeletePipeline·BatchDeleteArtifacts - Vector Collections — the vector facet in depth:
CreateVectorPipeline, the collection CRUD it shares with the other facets, and where BYO-embedding collections went - Templates —
ListTemplates·GetTemplate - Rules —
CreateRule·GetRule·ListRules·UpdateRule·DeleteRule - Sync —
TriggerDiscovery·TriggerIngestion·GetSyncStatus - Jobs —
TriggerIngest·GetIngestStatus·ListIngestJobs·RetryIngestJob
Retired surfaces
Documented here because they were previously part of this reference and calls against them now fail.
| Retired | Replacement |
|---|---|
GetCredential | None — reading a secret back in plaintext was the point of removal. |
ValidateCredential | None — it never performed a live check. |
GetEngine and /:bucket/tables/_engine | The reservation it carried is served by /:bucket/tables/reservation. |
/admin/api-keys | API-key management moved to IAM (dodil.iam.v1.ApiKeyService). K3 only verifies keys at the gateways. |
ListPipelinesRequest.store_entity_kind | facet — query as ?facet=vector|table|object|graph. |
Wire conventions
| HTTP request body | gRPC | |
|---|---|---|
| Field names | camelCase (pbjson) | as in .proto |
| Enums | wire-name strings ("SOURCE_STATUS_ACTIVE") | enum |
int64 | JSON strings | int64 |
| All fields | always emitted (no defaults dropped) | — |
HTTP query parameters are not uniform — each handler declares its own struct, and they disagree. Check the endpoint’s own page rather than assuming:
| Endpoint | Query casing | Notes |
|---|---|---|
GET /:bucket/ingest/jobs | camelCase | ?pipelineId=, ?ruleId=, ?pageSize=. status / status_filter are aliases for the same field. |
GET /:bucket/pipelines | snake_case | ?facet=, ?store_entity_id=, ?free_only=. No pagination. |
GET /:bucket/rules | snake_case | ?source_id=, ?pipeline_id=. No pagination. |
GET /:bucket/sources | — | Reads no query at all. No pagination. |
GET /admin/credentials | snake_case | ?source_id=, and ?provider= as the enum’s number (e.g. 10), not its name. |
GET /admin/templates | snake_case | ?category=, ?search=, ?facet=. |
Where a listing says “no pagination”, the HTTP handler passes pagination: None and returns every matching row; ?page_size= and ?page_token= are silently ignored. Pagination on those endpoints is reachable over gRPC only.
Endpoint roots
| Endpoint | When to use |
|---|---|
https://api.data.dodil.io | HTTP |
rpc.data.dodil.io:443 | gRPC |
Auth: bearer JWT in Authorization. See Conventions.
A note on routing authority
Rules carry both pipeline_id (the authoritative pointer) and binding (server-derived display info — pipeline name, kind, destination). Always route on pipeline_id. The binding is for rendering only and is empty when a rule outlives its pipeline.
Two display fields are similarly untrustworthy as identity:
Pipeline.nameis written as the template id, not the name you supplied, on the vector facet — your name lands ondestination.name. Render fromdestination.name. This is a logged source bug.ListPipelinesreturns two rows per vector collection — an index pipeline and its derived*_searchcounterpart, both pointing at the samedestination.storeEntityId. Deduplicate on that id when listing collections rather than pipelines.
Other protocols
Pipelines are configured here (control plane), but their outputs are ordinary engine data, reachable over every wire: query pipeline-written tables with psql on pg.uk-lon-1.dodil.io:5432, search pipeline-built collections with Qdrant/Pinecone SDKs, read source objects over S3. See Connect & wire adapters.
See also
- Core Concepts — every type signature, end-to-end
- Quickstart — wire all six entities in 5 minutes
- CLI Guide — every
dodil datacommand in this domain - Conventions — auth headers + error envelope