{ "openapi": "3.1.0", "info": { "title": "Stripe Sync Service", "version": "1.0.0", "description": "Stripe Sync Service — manage pipelines and webhook ingress.\n\n## Endpoints\n\n| Method | Path | Summary |\n|--------|------|---------|\n| GET | /health | Health check |\n| GET | /pipelines | List pipelines |\n| POST | /pipelines | Create pipeline |\n| GET | /pipelines/{id} | Retrieve pipeline |\n| PATCH | /pipelines/{id} | Update pipeline |\n| DELETE | /pipelines/{id} | Delete pipeline |\n| POST | /pipelines/{id}/sync | Run sync for a pipeline |\n| POST | /pipelines/{id}/simulate_webhook_sync | Simulate webhook sync by fetching events from the Stripe API |\n| POST | /pipelines/{id}/sync_workflow_test | Run sync using the workflow backfill loop (no Temporal) |\n| POST | /webhooks/{pipeline_id} | Ingest a Stripe webhook event |" }, "paths": { "/health": { "get": { "operationId": "health", "tags": [ "Status" ], "summary": "Health check", "responses": { "200": { "description": "Server is healthy", "content": { "application/json": { "schema": { "type": "object", "properties": { "ok": { "type": "boolean", "const": true }, "hostname": { "type": "string" } }, "required": [ "ok", "hostname" ], "additionalProperties": false } } } } } } }, "/pipelines": { "get": { "operationId": "pipelines.list", "tags": [ "Pipelines" ], "summary": "List pipelines", "responses": { "200": { "description": "List of pipelines", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Pipeline" } }, "has_more": { "type": "boolean" } }, "required": [ "data", "has_more" ], "additionalProperties": false } } } } } }, "post": { "operationId": "pipelines.create", "tags": [ "Pipelines" ], "summary": "Create pipeline", "parameters": [ { "in": "query", "name": "skip_check", "schema": { "description": "Skip connector validation checks", "type": "boolean" }, "description": "Skip connector validation checks" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "id": { "description": "Optional pipeline identifier. If omitted, the service generates one (e.g. pipe_abc123).", "type": "string", "minLength": 3, "maxLength": 64, "pattern": "^[a-z][a-z0-9_-]*$" }, "source": { "$ref": "#/components/schemas/SourceConfig" }, "destination": { "$ref": "#/components/schemas/DestinationConfig" }, "streams": { "description": "Selected streams to sync. All streams synced if omitted.", "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string", "description": "Stream (table) name to sync." }, "sync_mode": { "description": "How the source reads this stream. Defaults to full_refresh.", "type": "string", "enum": [ "incremental", "full_refresh" ] }, "backfill_limit": { "description": "Cap backfill to this many records, then mark the stream complete.", "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "name" ] } } }, "required": [ "source", "destination" ] } } } }, "responses": { "201": { "description": "Created pipeline", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pipeline" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": {} }, "required": [ "error" ], "additionalProperties": false } } } }, "409": { "description": "Pipeline id already exists", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": {} }, "required": [ "error" ], "additionalProperties": false } } } } } } }, "/pipelines/{id}": { "get": { "operationId": "pipelines.get", "tags": [ "Pipelines" ], "summary": "Retrieve pipeline", "parameters": [ { "in": "path", "name": "id", "schema": { "type": "string", "minLength": 3, "maxLength": 64, "pattern": "^[a-z][a-z0-9_-]*$", "description": "Unique pipeline identifier (e.g. pipe_abc123).", "example": "pipe_abc123" }, "required": true, "description": "Unique pipeline identifier (e.g. pipe_abc123)." } ], "responses": { "200": { "description": "Retrieved pipeline with status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pipeline" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": {} }, "required": [ "error" ], "additionalProperties": false } } } } } }, "patch": { "operationId": "pipelines.update", "tags": [ "Pipelines" ], "summary": "Update pipeline", "parameters": [ { "in": "path", "name": "id", "schema": { "type": "string", "minLength": 3, "maxLength": 64, "pattern": "^[a-z][a-z0-9_-]*$", "description": "Unique pipeline identifier (e.g. pipe_abc123).", "example": "pipe_abc123" }, "required": true, "description": "Unique pipeline identifier (e.g. pipe_abc123)." } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "id": { "description": "Optional pipeline identifier. If omitted, the service generates one (e.g. pipe_abc123).", "type": "string", "minLength": 3, "maxLength": 64, "pattern": "^[a-z][a-z0-9_-]*$" }, "source": { "$ref": "#/components/schemas/SourceConfig" }, "destination": { "$ref": "#/components/schemas/DestinationConfig" }, "streams": { "description": "Selected streams to sync. All streams synced if omitted.", "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string", "description": "Stream (table) name to sync." }, "sync_mode": { "description": "How the source reads this stream. Defaults to full_refresh.", "type": "string", "enum": [ "incremental", "full_refresh" ] }, "backfill_limit": { "description": "Cap backfill to this many records, then mark the stream complete.", "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "name" ] } }, "desired_status": { "description": "Set to \"paused\" to pause, \"active\" to resume, \"deleted\" to tear down.", "type": "string", "enum": [ "active", "paused", "deleted" ] } } } } } }, "responses": { "200": { "description": "Updated pipeline", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pipeline" } } } }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": {} }, "required": [ "error" ], "additionalProperties": false } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": {} }, "required": [ "error" ], "additionalProperties": false } } } }, "409": { "description": "Invalid status transition", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": {} }, "required": [ "error" ], "additionalProperties": false } } } } } }, "delete": { "operationId": "pipelines.delete", "tags": [ "Pipelines" ], "summary": "Delete pipeline", "parameters": [ { "in": "path", "name": "id", "schema": { "type": "string", "minLength": 3, "maxLength": 64, "pattern": "^[a-z][a-z0-9_-]*$", "description": "Unique pipeline identifier (e.g. pipe_abc123).", "example": "pipe_abc123" }, "required": true, "description": "Unique pipeline identifier (e.g. pipe_abc123)." } ], "responses": { "200": { "description": "Deleted pipeline", "content": { "application/json": { "schema": { "type": "object", "properties": { "id": { "type": "string" }, "deleted": { "type": "boolean", "const": true } }, "required": [ "id", "deleted" ], "additionalProperties": false } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": {} }, "required": [ "error" ], "additionalProperties": false } } } } } } }, "/pipelines/{id}/sync": { "post": { "operationId": "pipelines.sync", "tags": [ "Pipelines" ], "summary": "Run sync for a pipeline", "description": "Triggers an ad-hoc sync run for the pipeline and streams NDJSON messages (records, state, progress, eof) back to the client. Persists the ending sync_state on the pipeline so the next run resumes where this one left off.", "parameters": [ { "in": "path", "name": "id", "schema": { "type": "string", "minLength": 3, "maxLength": 64, "pattern": "^[a-z][a-z0-9_-]*$", "description": "Unique pipeline identifier (e.g. pipe_abc123).", "example": "pipe_abc123" }, "required": true, "description": "Unique pipeline identifier (e.g. pipe_abc123)." }, { "in": "query", "name": "time_limit", "schema": { "description": "Stop after N seconds", "type": "number" }, "description": "Stop after N seconds" }, { "in": "query", "name": "run_id", "schema": { "description": "Sync run identifier (resumes or starts fresh)", "type": "string" }, "description": "Sync run identifier (resumes or starts fresh)" }, { "in": "query", "name": "reset_state", "schema": { "description": "Ignore persisted sync state and start fresh (ending state is still saved)", "type": "boolean" }, "description": "Ignore persisted sync state and start fresh (ending state is still saved)" } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "properties": { "source": { "$ref": "#/components/schemas/SourceConfig" }, "destination": { "$ref": "#/components/schemas/DestinationConfig" }, "streams": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string", "description": "Stream (table) name to sync." }, "sync_mode": { "description": "How the source reads this stream. Defaults to full_refresh.", "type": "string", "enum": [ "incremental", "full_refresh" ] }, "backfill_limit": { "description": "Cap backfill to this many records, then mark the stream complete.", "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "name" ] } }, "sync_state": { "description": "Explicit sync checkpoint override for resumed ad-hoc runs", "$ref": "#/components/schemas/SyncState" } } } } } }, "responses": { "200": { "description": "Streaming NDJSON sync output", "content": { "application/x-ndjson": { "schema": { "type": "object", "properties": {}, "additionalProperties": {} } } } }, "404": { "description": "Pipeline not found", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": {} }, "required": [ "error" ], "additionalProperties": false } } } } } } }, "/pipelines/{id}/simulate_webhook_sync": { "post": { "operationId": "pipelines.simulate_webhook_sync", "tags": [ "Pipelines" ], "summary": "Simulate webhook sync by fetching events from the Stripe API", "description": "Fetches events from /v1/events using the pipeline's Stripe API key, then pipes them as input into the sync engine's push mode. This exercises the same code path as real webhooks without needing webhook delivery.", "parameters": [ { "in": "path", "name": "id", "schema": { "type": "string", "minLength": 3, "maxLength": 64, "pattern": "^[a-z][a-z0-9_-]*$", "description": "Unique pipeline identifier (e.g. pipe_abc123).", "example": "pipe_abc123" }, "required": true, "description": "Unique pipeline identifier (e.g. pipe_abc123)." }, { "in": "query", "name": "created_after", "schema": { "description": "Only fetch events created after this Unix timestamp (default: 24 hours ago)", "type": "number" }, "description": "Only fetch events created after this Unix timestamp (default: 24 hours ago)" }, { "in": "query", "name": "limit", "schema": { "description": "Max events to fetch (default: all)", "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "description": "Max events to fetch (default: all)" } ], "responses": { "200": { "description": "Streaming NDJSON sync output", "content": { "application/x-ndjson": { "schema": { "type": "object", "properties": {}, "additionalProperties": {} } } } }, "400": { "description": "Pipeline source is not Stripe", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": {} }, "required": [ "error" ], "additionalProperties": false } } } }, "404": { "description": "Pipeline not found", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": {} }, "required": [ "error" ], "additionalProperties": false } } } } } } }, "/pipelines/{id}/sync_workflow_test": { "post": { "operationId": "pipelines.sync_workflow_test", "tags": [ "Pipelines" ], "summary": "Run sync using the workflow backfill loop (no Temporal)", "description": "Exercises the same backfill loop code that the Temporal workflow uses, but runs inline without a Temporal server. Useful for testing the full workflow logic end-to-end.", "parameters": [ { "in": "path", "name": "id", "schema": { "type": "string", "minLength": 3, "maxLength": 64, "pattern": "^[a-z][a-z0-9_-]*$", "description": "Unique pipeline identifier (e.g. pipe_abc123).", "example": "pipe_abc123" }, "required": true, "description": "Unique pipeline identifier (e.g. pipe_abc123)." }, { "in": "query", "name": "time_limit", "schema": { "description": "Time limit per iteration (seconds)", "type": "number" }, "description": "Time limit per iteration (seconds)" } ], "responses": { "200": { "description": "Backfill result with final eof and sync state", "content": { "application/json": { "schema": { "type": "object", "properties": { "eof": { "type": "object", "properties": {}, "additionalProperties": {} }, "sync_state": { "type": "object", "properties": {}, "additionalProperties": {} } }, "required": [ "eof" ], "additionalProperties": false } } } }, "404": { "description": "Pipeline not found", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": {} }, "required": [ "error" ], "additionalProperties": false } } } } } } }, "/webhooks/{pipeline_id}": { "post": { "operationId": "webhooks.push", "tags": [ "Webhooks" ], "summary": "Ingest a Stripe webhook event", "description": "Receives a raw Stripe webhook event, verifies its signature using the pipeline's webhook secret, and enqueues it for processing by the active pipeline.", "parameters": [ { "in": "path", "name": "pipeline_id", "schema": { "type": "string", "example": "pipe_abc123" }, "required": true } ], "responses": { "200": { "description": "Event accepted", "content": { "text/plain": { "schema": { "type": "string", "const": "ok" } } } } } } } }, "components": { "schemas": { "SourceConfig": { "oneOf": [ { "type": "object", "properties": { "type": { "type": "string", "const": "stripe" }, "stripe": { "$ref": "#/components/schemas/SourceStripeConfig" } }, "required": [ "type", "stripe" ] } ], "type": "object", "discriminator": { "propertyName": "type" } }, "SourceStripeConfig": { "type": "object", "properties": { "api_key": { "type": "string", "description": "Stripe API key (sk_test_... or sk_live_...)" }, "account_id": { "type": "string", "description": "Stripe account ID (resolved from API if omitted)" }, "account_created": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "description": "Stripe account creation timestamp in unix seconds (resolved from API if omitted)" }, "livemode": { "type": "boolean", "description": "Whether this is a live mode sync" }, "api_version": { "type": "string", "enum": [ "2026-03-25.dahlia", "2026-02-25.clover", "2026-01-28.clover", "2025-12-15.clover", "2025-11-17.clover", "2025-10-29.clover", "2025-09-30.clover", "2025-08-27.basil", "2025-07-30.basil", "2025-06-30.basil", "2025-05-28.basil", "2025-04-30.basil", "2025-03-31.basil", "2025-02-24.acacia", "2025-01-27.acacia", "2024-12-18.acacia", "2024-11-20.acacia", "2024-10-28.acacia", "2024-09-30.acacia", "2024-06-20", "2024-04-10", "2024-04-03", "2023-10-16", "2023-08-16", "2022-11-15", "2022-08-01", "2020-08-27", "2020-03-02", "2019-12-03", "2019-11-05", "2019-10-17", "2019-10-08", "2019-09-09", "2019-08-14", "2019-05-16", "2019-03-14", "2019-02-19", "2019-02-11", "2018-11-08", "2018-10-31", "2018-09-24", "2018-09-06", "2018-08-23", "2018-07-27", "2018-05-21", "2018-02-28", "2018-02-06", "2018-02-05", "2018-01-23", "2017-12-14", "2017-08-15" ] }, "base_url": { "type": "string", "format": "uri", "description": "Override the Stripe API base URL (e.g. http://localhost:12111 for stripe-mock)" }, "webhook_url": { "type": "string", "format": "uri", "description": "URL for managed webhook endpoint registration" }, "webhook_secret": { "type": "string", "description": "Webhook signing secret (whsec_...) for signature verification" }, "websocket": { "type": "boolean", "description": "Enable WebSocket streaming for live events" }, "poll_events": { "type": "boolean", "description": "Enable events API polling for incremental sync after backfill" }, "webhook_port": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991, "description": "Port for built-in webhook HTTP listener (e.g. 4242)" }, "revalidate_objects": { "type": "array", "items": { "type": "string" }, "description": "Object types to re-fetch from Stripe API on webhook (e.g. [\"subscription\"])" }, "backfill_limit": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991, "description": "Max objects to backfill per stream (useful for testing)" }, "rate_limit": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991, "description": "Override max requests per second (default: auto-derived from API key mode — 20 live, 10 test)." } }, "required": [ "api_key" ], "additionalProperties": false }, "DestinationConfig": { "oneOf": [ { "type": "object", "properties": { "type": { "type": "string", "const": "postgres" }, "postgres": { "$ref": "#/components/schemas/DestinationPostgresConfig" } }, "required": [ "type", "postgres" ] }, { "type": "object", "properties": { "type": { "type": "string", "const": "google_sheets" }, "google_sheets": { "$ref": "#/components/schemas/DestinationGoogleSheetsConfig" } }, "required": [ "type", "google_sheets" ] } ], "type": "object", "discriminator": { "propertyName": "type" } }, "DestinationPostgresConfig": { "type": "object", "properties": { "url": { "type": "string", "description": "Postgres connection string" }, "connection_string": { "type": "string", "description": "Deprecated alias for url; prefer url" }, "schema": { "default": "public", "type": "string", "description": "Target schema name (e.g. \"stripe\")" }, "batch_size": { "default": 100, "type": "number", "description": "Records to buffer before flushing" }, "aws": { "type": "object", "properties": { "host": { "type": "string", "description": "Postgres host for RDS IAM auth" }, "port": { "default": 5432, "type": "number", "description": "Postgres port for RDS IAM auth" }, "database": { "type": "string", "description": "Database name for RDS IAM auth" }, "user": { "type": "string", "description": "Database user for RDS IAM auth" }, "region": { "type": "string", "description": "AWS region for RDS instance" }, "role_arn": { "type": "string", "description": "IAM role ARN to assume (cross-account)" }, "external_id": { "type": "string", "description": "External ID for STS AssumeRole" } }, "required": [ "host", "database", "user", "region" ], "additionalProperties": false, "description": "AWS RDS IAM authentication config" }, "ssl_ca_pem": { "type": "string", "description": "PEM-encoded CA certificate for SSL verification (required for verify-ca / verify-full with a private CA)" } }, "additionalProperties": false }, "DestinationGoogleSheetsConfig": { "type": "object", "properties": { "client_id": { "type": "string", "description": "Google OAuth2 client ID (env: GOOGLE_CLIENT_ID)" }, "client_secret": { "type": "string", "description": "Google OAuth2 client secret (env: GOOGLE_CLIENT_SECRET)" }, "access_token": { "type": "string", "description": "OAuth2 access token" }, "refresh_token": { "type": "string", "description": "OAuth2 refresh token" }, "spreadsheet_id": { "type": "string", "description": "Target spreadsheet ID (created if omitted)" }, "spreadsheet_title": { "default": "Stripe Sync", "type": "string", "description": "Title when creating a new spreadsheet" }, "batch_size": { "default": 50, "type": "number", "description": "Rows per Sheets API append call" } }, "required": [ "access_token", "refresh_token" ], "additionalProperties": false }, "SyncState": { "type": "object", "properties": { "source": { "$ref": "#/components/schemas/SourceState" }, "destination": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {}, "description": "Destination connector state." }, "sync_run": { "type": "object", "properties": { "run_id": { "description": "Identifies a finite backfill run. Omit for continuous sync.", "type": "string" }, "time_ceiling": { "description": "Frozen upper bound (ISO 8601). Set on first invocation when run_id is present; reused on continuation.", "type": "string" }, "progress": { "description": "Accumulated progress from prior requests in this run.", "$ref": "#/components/schemas/ProgressPayload" } }, "required": [ "progress" ], "description": "Engine-managed run state — run_id, time_ceiling, accumulated progress." } }, "required": [ "source", "destination", "sync_run" ], "description": "Full sync checkpoint with separate sections for source, destination, and sync run. Connectors only see their own section; the engine manages routing." }, "SourceState": { "type": "object", "properties": { "streams": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {}, "description": "Per-stream checkpoint data, keyed by stream name." }, "global": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {}, "description": "Source-wide state shared across all streams." } }, "required": [ "streams", "global" ], "description": "Source connector state — cursors, backfill progress, events cursors." }, "RunStatus": { "type": "string", "enum": [ "started", "succeeded", "failed" ], "description": "succeeded = all streams completed/skipped; failed = connection_status failed OR any stream errored." }, "StreamProgress": { "type": "object", "properties": { "status": { "type": "string", "enum": [ "not_started", "started", "completed", "skipped", "errored" ], "description": "Current state, derived from stream_status events." }, "state_count": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991, "description": "Number of state checkpoints for this stream." }, "record_count": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991, "description": "Records synced for this stream in this run." }, "message": { "description": "Human-readable status message (error reason, skip reason, etc).", "type": "string" }, "total_range": { "description": "Full backfill time span for this stream.", "type": "object", "properties": { "gte": { "type": "string", "description": "Inclusive lower bound (ISO 8601)." }, "lt": { "type": "string", "description": "Exclusive upper bound (ISO 8601)." } }, "required": [ "gte", "lt" ] }, "completed_ranges": { "description": "Completed time sub-ranges within the total_range.", "type": "array", "items": { "type": "object", "properties": { "gte": { "type": "string", "description": "Inclusive lower bound (ISO 8601)." }, "lt": { "type": "string", "description": "Exclusive upper bound (ISO 8601)." } }, "required": [ "gte", "lt" ] } } }, "required": [ "status", "state_count", "record_count" ], "description": "Per-stream progress snapshot." }, "ProgressPayload": { "type": "object", "properties": { "started_at": { "type": "string", "description": "When this sync started (ISO 8601); generally equals time_ceiling." }, "elapsed_ms": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991, "description": "Wall-clock milliseconds since the sync run started." }, "global_state_count": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991, "description": "Total source_state messages observed so far." }, "connection_status": { "description": "Set when source or destination emits connection_status: failed.", "type": "object", "properties": { "status": { "type": "string", "enum": [ "succeeded", "failed" ], "description": "Whether the connection check passed." }, "message": { "description": "Human-readable explanation of the check result.", "type": "string" } }, "required": [ "status" ] }, "derived": { "type": "object", "properties": { "status": { "$ref": "#/components/schemas/RunStatus" }, "records_per_second": { "type": "number", "description": "Overall throughput for the entire run." }, "states_per_second": { "type": "number", "description": "State checkpoints per second." } }, "required": [ "status", "records_per_second", "states_per_second" ], "description": "Computed aggregates." }, "streams": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/components/schemas/StreamProgress" }, "description": "Per-stream progress, keyed by stream name." } }, "required": [ "started_at", "elapsed_ms", "global_state_count", "derived", "streams" ], "description": "Periodic sync progress emitted by the engine as a top-level message. Each emission is a full replacement." }, "Pipeline": { "type": "object", "properties": { "id": { "type": "string", "minLength": 3, "maxLength": 64, "pattern": "^[a-z][a-z0-9_-]*$", "description": "Unique pipeline identifier (e.g. pipe_abc123)." }, "source": { "$ref": "#/components/schemas/SourceConfig" }, "destination": { "$ref": "#/components/schemas/DestinationConfig" }, "streams": { "description": "Selected streams to sync. All streams synced if omitted.", "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string", "description": "Stream (table) name to sync." }, "sync_mode": { "description": "How the source reads this stream. Defaults to full_refresh.", "type": "string", "enum": [ "incremental", "full_refresh" ] }, "backfill_limit": { "description": "Cap backfill to this many records, then mark the stream complete.", "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "name" ], "additionalProperties": false } }, "desired_status": { "default": "active", "description": "User-controlled lifecycle state. Set via PATCH to pause, resume, or delete.", "type": "string", "enum": [ "active", "paused", "deleted" ] }, "status": { "default": "setup", "description": "Workflow-controlled execution state. Updated by the Temporal workflow.", "type": "string", "enum": [ "setup", "backfill", "ready", "paused", "teardown", "error" ] }, "sync_state": { "description": "Latest full sync checkpoint emitted by the engine. Includes source, destination, and sync-run state for the next request.", "$ref": "#/components/schemas/SyncState" } }, "required": [ "id", "source", "destination", "desired_status", "status" ], "additionalProperties": false } } } }