New to Kestra?
Use blueprints to kickstart your first workflows.
Fetch a JSON API and upsert the full feed into a DocumentDB collection daily with Kestra, with retry, idempotency, audit markers, and Slack alerts.
Ingest a JSON HTTP API into Amazon DocumentDB (or any MongoDB-compatible endpoint exposed through the
DocumentDB Data REST API) with a scheduled, idempotent, fully orchestrated pipeline. This blueprint
fetches an entire JSON feed, validates it, and upserts every record into a DocumentDB collection keyed
on a deterministic external_id, so daily runs, manual replays, and backfills overwrite documents in
place instead of accumulating duplicates. It solves the classic API-to-database ingestion problem:
paginating the whole feed (not just the first batch), guarding against broken upstreams, retrying
transient failures, keeping the load idempotent, and recording an audit trail of every run.
fetch_api (io.kestra.plugin.core.http.Request) calls the configured api_url with a GET and
retries up to three times on transient errors.guard_array (io.kestra.plugin.core.execution.Fail) fails fast when the body is empty or is not
a JSON array, so a broken upstream never triggers partial writes.ingest_records (io.kestra.plugin.core.flow.ForEach) iterates the full array. For each record it
runs read_existing (io.kestra.plugin.documentdb.Read with fetchType: FETCH_ONE) to check for
an existing document, then upsert_record (io.kestra.plugin.core.flow.If) branches to
io.kestra.plugin.documentdb.Update when the document exists or io.kestra.plugin.documentdb.Insert
when it does not. Because the Update task has no native upsert flag, this read-then-branch pattern
emulates an upsert. The raw record is stored under a record field and ingest_count is incremented
on every update.count_ingested (io.kestra.plugin.documentdb.Read with fetchType: STORE) counts the collection
after the load for the run summary.insert_run_marker (io.kestra.plugin.documentdb.Insert) writes a schedule-aware audit marker to
the ingestion_runs collection (source, source record count, collection size, status, execution id,
schedule date).log_summary (io.kestra.plugin.core.log.Log) prints a one-line ingestion summary.external_id, so re-runs and backfills never duplicate documents.ingestion_runs collection.DocumentDB has no built-in scheduler, no feed-level orchestration, and no native upsert on its Update
action. Kestra fills that gap. The io.kestra.plugin.core.trigger.Schedule trigger fires the load
daily (and can be swapped for an event or webhook trigger), every task carries declarative retry
policies, the errors block routes failures to Slack, and the whole pipeline is version-controlled
YAML you can diff, review, and replay. The emulated upsert, fail-fast guard, and audit marker are all
expressed declaratively, giving you lineage and observability that a raw cron job hitting the
DocumentDB API cannot provide.
/data/v1/action/* HTTP API).database and both collections (customers, ingestion_runs) created beforehand, or
auto-created on first write by your service.business_key input.DOCUMENTDB_HOST: base HTTPS endpoint of the DocumentDB Data REST API, for example https://your-documentdb.example.com.DOCUMENTDB_USERNAME: basic-auth username for the DocumentDB API.DOCUMENTDB_PASSWORD: basic-auth password for the DocumentDB API.SLACK_WEBHOOK: Slack incoming webhook URL used by the failure alert.database and collection variables, the api_url, and the business_key input to match your data.Schedule trigger take over, and create a unique index on external_id as a backstop.Schedule trigger with a webhook or Flow trigger to ingest on demand or downstream of another flow.fetch_api and ingest_records.api_url and looping over a list of sources.count_ingested to a monitoring or alerting destination.