Meili CDC Docs

REST API

Everything the dashboard does goes through a JSON API under /api/v1. This page covers authentication, errors and every route; the field-level reference is docs/api.md in the repository.

Basics

  • Base path /api/v1; JSON in and out (Content-Type: application/json).
  • Request bodies are limited to 16 MiB (1 MiB on some account routes, 64 MiB for webhook ingest).
  • Durations are strings such as "30s"; times are RFC 3339.
  • Secrets are never returned: they come back as "••••••", and sending the mask back keeps the stored value.
  • Types are defined in internal/model (Task, Status, TaskView, Connector, Destination, DLQEntry, LogEntry, Schema) and internal/diff (Report, SchemaReport).

Authentication

MethodUse
Session cookie cdc_sessionCreated by POST /auth/login, /auth/setup or /auth/invite/accept. Valid 7 days, sliding. Cookie-authenticated writes must send an Origin (or Referer) matching the host (CSRF protection); browsers do it automatically.
Bearer tokenAuthorization: Bearer $CDC_ADMIN_TOKEN: the static admin token, acting as an admin named "API token". GET /events also accepts ?token=.
Webhook signatureOnly for POST /ingest/{id} on webhook tasks with a signing secret; see Webhook.

MCP tokens (cdcmcp_…) authenticate only at /mcp, not at the REST API. The role each route needs is listed in the permission matrix.

TOKEN=$CDC_ADMIN_TOKEN
CDC=https://cdc.example.com
curl -s -H "Authorization: Bearer $TOKEN" "$CDC/api/v1/tasks" | jq '.[] | {id, state: .status.state}'

# Or sign in and keep the cookie (send Origin on writes)
curl -s -c jar -H 'Content-Type: application/json' -H "Origin: $CDC" \
  -d '{"email":"you@example.com","password":"…"}' "$CDC/api/v1/auth/login"
curl -s -b jar "$CDC/api/v1/auth/me"

Errors

Errors are JSON: {"error": "message"}, with details (a list of messages) for validation errors and code when Meilisearch reported the error.

StatusWhen
400Invalid JSON body, unknown batch action, bad parameters, invalid webhook payload.
401Not authenticated ({"error":"authentication required"}), or an invalid webhook signature.
403Role too low ({"error":"requires role moderator"}), owner protection, or cross-origin request refused.
404Unknown task, connector, destination, index or route.
409Conflict: duplicate id, a resource still in use, a running task writing to an index you delete, a primary key mismatch, a diff already running, single-instance mode, the last admin.
422Validation failed; details lists every problem, for example ["name is required", "index.uid is required and may only contain a-z A-Z 0-9 - _"].
429Too many failed sign-ins; see the Retry-After header.
4xx from MeilisearchPassed through with Meilisearch's message and code (index and instance routes).
503, 504Webhook ingest: task not running, or confirmation took longer than 60 s.

Health and overview

RouteResult
GET /health (public){"status":"ok","meilisearch":{"status":"available","version":"1.x","destination":"…"}}
GET /overviewTasks by state, totals, rate, the default instance, every destination, registered source types.
GET /eventsServer-Sent Events; see live events.

Tasks

RouteNotes
GET /tasks?state=&q=&tag=[TaskView] (task + status), secrets masked.
POST /tasks[?start=true]Body: a task; without id one is generated. 201 TaskView.
GET /tasks/{id}, PUT /tasks/{id}, DELETE /tasks/{id}?dropSource=true&deleteIndex=<uid>Update restarts a running task; delete returns 204.
POST /tasks/{id}/{action}start, stop, pause, resume, restart, resync, reset-checkpoint.
POST /tasks/batch{"ids":[…],"action":"…"} (the actions above except reset-checkpoint, plus delete) → {"results":[{"id","ok","error"}]}.
POST /tasks/testBody: a task → {"ok","error","schema","sample":[5 docs],"primaryKey"}.
GET /tasks/export, POST /tasks/importExport with secrets masked; import [Task] → {"created":n,"errors":[…]}.
GET /tasks/{id}/logs?limit=200[LogEntry].
GET /tasks/{id}/metrics{"points":[{"t","rate","lagMs","upserted","deleted"}],"checkpoint":{…}}: about 10 minutes at 2 s resolution.
GET /tasks/{id}/settings, POST /tasks/{id}/settings/applyDesired versus live index settings and drift; apply the desired settings (admin).
POST /ingest/{id}Push changes to a webhook task; see Webhook.
# Create a task on a saved connector and start it
curl -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' "$CDC/api/v1/tasks?start=true" -d '{
  "id": "products", "name": "Products",
  "source": {"connectorId": "pg-main", "table": "products"},
  "index": {"uid": "products"},
  "sync": {"safety": {"maxDeleteRatio": 0.2, "zeroDowntimeResync": true}}
}'

# Resync it
curl -X POST -H "Authorization: Bearer $TOKEN" "$CDC/api/v1/tasks/products/resync"

Data quality

RouteNotes
GET /tasks/{id}/schema-checkSchemaReport: primary key check, fields with coverage and settings, issues.
POST /tasks/{id}/diff{"sampleLimit":50,"compareFields":true} → 202 {"status":"running"}.
GET /tasks/{id}/diffThe last Report: status, counts, missing, extra, mismatched, inSync, samples, and repair counts when it repaired.
POST /tasks/{id}/diff/repair{"missing":true,"mismatched":true,"extra":false} → 202 {"status":"running"}; poll GET /tasks/{id}/diff for the result. (docs/api.md describes a synchronous {"upserted","deleted"} response; the server runs it in the background.)
GET /tasks/{id}/dlq?limit=100[DLQEntry].
POST /tasks/{id}/dlq/replay{"ids":[…]} (empty = all) → {"replayed":n,"failed":n}.
DELETE /tasks/{id}/dlq{"ids":[…]} (empty = all) → {"deleted":n}.

Indexes and Meilisearch instances

Every index and instance route takes ?destination=<id> (the default destination when omitted).

RouteNotes
GET /indexesIndexes with document counts and managedBy tasks. ?destination=* returns every instance, grouped.
POST /indexes, GET /indexes/{uid}, DELETE /indexes/{uid}?confirm={uid}Delete is 409 while a running task writes to the index.
GET /indexes/{uid}/settings, POST …/settings/preview, PATCH …/settings, POST …/settings/resetPATCH waits up to 30 s and returns {"taskUid","status","error"}.
PUT /indexes/{uid}/primary-key409 when the index has documents.
POST /indexes/{uid}/search{"q","filter","sort","limit","facets","hybrid"} → Meilisearch's response.
GET /indexes/{uid}/documents?limit=20&offset=0{"results":[…],"total":n}.
POST /indexes/swap, POST /indexes/{uid}/compactSwap: {"a","b","rename"}.
GET /meili/tasks, POST /meili/tasks/cancel, GET /meili/statsThe instance's task queue (indexUid, status, type, limit, from).
POST /meili/dumps, POST /meili/snapshots, GET/PATCH /meili/experimental-featuresInstance administration.
curl -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  "$CDC/api/v1/indexes/products/search?destination=eu" -d '{"q":"lamp","filter":"price < 50","limit":5}'

Connectors and destinations

RouteNotes
GET/POST /connectors, GET/PUT/DELETE /connectors/{id}Delete is 409 while tasks use it.
POST /connectors/test, POST /connectors/{id}/testTest unsaved values or a saved connector → {"ok","error","latencyMs","version","tables"}.
GET /connectors/{id}/tables?q=Discovered tables, collections, topics or streams (max 1,000).
GET/POST /destinations, GET/PUT/DELETE /destinations/{id}DestinationView with health, usedBy, sync. 409 in single-instance mode.
POST /destinations/{id}/default, POST /destinations/test, POST /destinations/{id}/test, POST /destinations/{id}/health/checkMake default; test; check health now.

Accounts and settings

RouteNotes
GET /auth/config (public){"setupRequired","smtpConfigured","passwordLogin"}; signed-in callers also get singleDestination, telegramConfigured and onboarding counts.
POST /auth/setup, /auth/login, /auth/logout, /auth/forgot, /auth/resetSetup returns 409 once a user exists; forgot always answers 202 (or 409 without SMTP).
GET /auth/invite/{token}, POST /auth/invite/acceptInvitation details and acceptance.
GET/PATCH /auth/me, POST /auth/me/passwordThe current user.
GET/POST /users, PATCH/DELETE /users/{id}, POST /users/{id}/passwordAdmin; owner rules apply.
GET/POST /invitations, DELETE /invitations/{id}The link is returned once.
GET/PUT /settings/smtp, POST /settings/smtp/test{"host","port","username","password","from","tls","publicUrl"}.
GET/PUT /settings/telegram, POST /settings/telegram/test{"botToken","apiUrl"}; test with {"chatId"}.
GET/POST /alerts/rules, PUT/DELETE /alerts/rules/{id}, POST /alerts/rules/{id}/testSee Alerts.
GET /alerts/channels, GET /alerts/events, GET /alerts/activeConfigured channels, history, firing alerts.
GET/PUT /settings/mcp, POST /settings/mcp/reset-policy, GET/POST /mcp/tokens, POST /mcp/tokens/{id}/rotate, DELETE /mcp/tokens/{id}See MCP.
GET /audit?limit=200Audit entries, newest first.

Outside /api/v1

PathNotes
/metricsPrometheus metrics (authenticated).
/healthzok, public.
/mcpMCP endpoint, cdcmcp_ tokens.
/debug/pprof/With CDC_PPROF=true.
/The dashboard (unless CDC_DISABLE_UI).

Meili CDC user guide · last updated 2026-10-26 · Edit this page on GitHub

meilisearch-cdc is open source. Meilisearch is a trademark of Meili SAS; this project is not affiliated with it.