HTTP taps cannot use the platform-data callback — the
DATRIS_PLATFORM_* query API is reachable only from scripts running on the platform. If your
tap’s fetch logic depends on data already stored in Datris, keep it as a Python tap.The request
On each run, Datris sends:
The request times out after the platform’s tap timeout (default 300 seconds, the same knob as
script taps). Answer well within it — see Long fetches.
The response
Reply200 OK with the tap envelope:
Anything else — a non-200 status, a timeout, a malformed envelope — records a failed run, with
your response body (truncated) as the error message. Failed scheduled runs enter the platform’s
normal cron retry ladder.
document-type records use the same shape as document taps:
{"uri": "...", "filename": "...", "content": "<base64>", "content_hash": "...", "metadata": {...}}.
The whole response is capped at the platform’s tap output limit (default 100 MB). Bigger
fetches should be chunked — see below.
Auth
If the tap references a secret, the secret’sendpoint_token field is sent as
Authorization: Bearer <value>. That is the only secret field ever forwarded — upstream
source credentials (API keys for the systems your service fetches from) belong to your service’s
own configuration, not to Datris. A tap that names a secret with no usable endpoint_token
fails loudly before the call.
Use https:// for any non-local endpoint — the token travels in a header.
Long fetches: chunk with state
Multi-minute HTTP requests are fragile through proxies and load balancers. Don’t answer one run with a giant slow response — return one page quickly plus astate cursor, and let the next
run continue where you left off:
- Run 1: request has
"state": null→ fetch the first page, respond with"data": [...page 1...], "state": {"offset": 1000}. - Run 2: request has
"state": {"offset": 1000}→ fetch the next page, respond with"data": [...page 2...], "state": {"offset": 2000}. - Caught up: respond
"data": [], "state": {"offset": 2000}— a cleanno_recordsrun that keeps the bookmark.
A minimal endpoint in Rust
Any HTTP stack works; here is the whole contract in one axum handler:net/http + encoding/json), Node/TypeScript
(express/fastify), or a serverless function — read the JSON body, write the envelope.
Creating an HTTP tap
- UI: Catalog → Create Tap → choose HTTP Endpoint, paste the URL, optionally attach a
secret whose
endpoint_tokenyour service checks. Test Script POSTs to your endpoint (withtestLimit: null— the wizard does not cap HTTP-tap samples) and previews the response without persisting.
The request comes from inside the Datris container. For an endpoint running on the same
machine as Docker, use
http://host.docker.internal:<port>/... — localhost would point at
the container itself and the connection will be refused.- CLI:
datris tap create --name my-tap --kind http --endpoint-url https://taps.example.com/my-tap --pipeline my-pipeline --cron "0 0 6 * * ?" - MCP:
create_tapwithkind: "http"andendpoint_url.
run_tap, get_pipeline_status polling, and the sync-state
viewer all work exactly as they do for Python taps. What doesn’t apply: AI script
generation/fix/review/optimize (there is no script), pip packages, script storage, and the
platform-data callback.