Skip to Content
We are live but in Staging 🎉
PipelinesAPI ReferenceOverview

Pipelines — API Reference

The Pipelines domain spans three gRPC services across three proto packages:

ServicePackageOwns
SourceServicedodil.data.source.v1Sources (external data sources + the auto-created internal S3 source) and Credentials (OAuth / API keys / PATs / access keys)
PipelineServicedodil.data.pipeline.v1Pipelines and their destinations (the three facet creators + CRUD), Template catalog browsing, and pipeline-chain teardown
IngestServicedodil.data.ingest.v1Ingest 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

  • SourcesCreateSource · GetSource · ListSources · UpdateSource · DeleteSource
  • CredentialsStoreCredential · ListCredentials · DeleteCredential · OAuth flow (GetOAuthUrl · ExchangeOAuthCode · RefreshOAuthToken)
  • PipelinesCreateVectorPipeline · 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
  • TemplatesListTemplates · GetTemplate
  • RulesCreateRule · GetRule · ListRules · UpdateRule · DeleteRule
  • SyncTriggerDiscovery · TriggerIngestion · GetSyncStatus
  • JobsTriggerIngest · GetIngestStatus · ListIngestJobs · RetryIngestJob

Retired surfaces

Documented here because they were previously part of this reference and calls against them now fail.

RetiredReplacement
GetCredentialNone — reading a secret back in plaintext was the point of removal.
ValidateCredentialNone — it never performed a live check.
GetEngine and /:bucket/tables/_engineThe reservation it carried is served by /:bucket/tables/reservation.
/admin/api-keysAPI-key management moved to IAM (dodil.iam.v1.ApiKeyService). K3 only verifies keys at the gateways.
ListPipelinesRequest.store_entity_kindfacet — query as ?facet=vector|table|object|graph.

Wire conventions

HTTP request bodygRPC
Field namescamelCase (pbjson)as in .proto
Enumswire-name strings ("SOURCE_STATUS_ACTIVE")enum
int64JSON stringsint64
All fieldsalways 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:

EndpointQuery casingNotes
GET /:bucket/ingest/jobscamelCase?pipelineId=, ?ruleId=, ?pageSize=. status / status_filter are aliases for the same field.
GET /:bucket/pipelinessnake_case?facet=, ?store_entity_id=, ?free_only=. No pagination.
GET /:bucket/rulessnake_case?source_id=, ?pipeline_id=. No pagination.
GET /:bucket/sourcesReads no query at all. No pagination.
GET /admin/credentialssnake_case?source_id=, and ?provider= as the enum’s number (e.g. 10), not its name.
GET /admin/templatessnake_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

EndpointWhen to use
https://api.data.dodil.ioHTTP
rpc.data.dodil.io:443gRPC

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.name is written as the template id, not the name you supplied, on the vector facet — your name lands on destination.name. Render from destination.name. This is a logged source bug.
  • ListPipelines returns two rows per vector collection — an index pipeline and its derived *_search counterpart, both pointing at the same destination.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