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 withtestLimitset 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.