Skip to content

API reference

Trigger a bounded extraction run

POST
/v1/syncs

Starts, resumes or returns an extraction run for one connection and a window of at most 31 days.

Idempotency-Key is required. Reusing a key with the same window resumes or returns the durable run rather than starting a second one; changed intent needs a new key. At most one live lease may execute the same exact workspace, connection, property and date window. A different key contending for that window receives window_in_progress before a run row, sequence or provider request is allocated; retry that same key after the current run finishes or its lease expires. Partly overlapping windows remain independent.

Strict calendar and interval validation occurs before extraction. Completion is checked in the property’s returned timezone; there is no earlier UTC completion gate. Publication compares the immutable extraction time first; the creation sequence is only the deterministic tie-break for equal millisecond timestamps. Both values are checked atomically against the current head’s matching source run.

Idempotency-Key
required
string
/^[A-Za-z0-9._:-]{8,128}$/

8–128 characters from A-Za-z0-9._:-. Identifies one logical extraction.

The sync request body. Unknown fields are rejected rather than ignored.

MetricQuery deliberately repeats these five fields rather than composing this schema with allOf: additionalProperties is evaluated only against the properties in the same schema object, so an allOf branch carrying additionalProperties: false would reject the query body’s metric and dimensions and make the composed schema match nothing.

object
workspaceId
required

Must equal the API key’s own workspace.

string
/^[A-Za-z0-9_-]{1,128}$/
connectionId
required
string
/^[A-Za-z0-9_-]{1,128}$/
propertyId
required

GA4 numeric property id, as a string.

string
/^[1-9][0-9]{0,19}$/
startDate
required

Calendar date in the property’s reporting timezone.

string format: date
endDate
required

Inclusive. The closed interval must contain 1–31 days. For sync it must also be before today in the property’s returned timezone.

string format: date
Example
{
"workspaceId": "your_workspace",
"connectionId": "your_connection",
"propertyId": "123456789",
"startDate": "2026-08-31",
"endDate": "2026-09-04"
}

The run reached completed, partial or superseded. HTTP 200 alone does not imply full publication; check state and the expected publishedDates.

object
One of:

errorCode is conditionally present: required for failed and forbidden in every other state. The four nullable fields are always present — the gateway rejects an upstream response that omits them. Completed, partial and superseded records have non-null timezone and quality. Completed and superseded quality is reliable (both limitation flags false and no sampling); partial quality names at least one thresholding, loss or sampling limitation. A failed record retains null completion/publication fields and a required classified errorCode.

object
state
Allowed value: failed
completedAt
publishedDates
state
Allowed values: completed partial superseded

The run is in progress — pending, extracting, raw_committed or loaded. Poll GET /v1/syncs/{runId}; a successful polling GET returns 200 even while the run remains in progress, so inspect its state.

object
One of:

errorCode is conditionally present: required for failed and forbidden in every other state. The four nullable fields are always present — the gateway rejects an upstream response that omits them. Completed, partial and superseded records have non-null timezone and quality. Completed and superseded quality is reliable (both limitation flags false and no sampling); partial quality names at least one thresholding, loss or sampling limitation. A failed record retains null completion/publication fields and a required classified errorCode.

object
state
Allowed value: failed
completedAt
publishedDates
state
Allowed values: pending extracting raw_committed loaded

invalid_json — the body is absent, not valid JSON, or not valid UTF-8.

invalid_request, invalid_window, invalid_idempotency_key, invalid_provider_request, or incomplete_day when the window includes a day still in progress in the property’s timezone.

invalid_query — the URL carried a query delimiter, including a bare ?. The route table checks this before it reads the body, so POST /v1/syncs?anything is refused here rather than at 404.

object
error
required
object
code
required
string
message
required
string
error
object
code
Allowed values: invalid_json invalid_request invalid_window invalid_idempotency_key invalid_provider_request incomplete_day invalid_query

unauthorized — missing, unknown, expired or revoked key.

object
error
required
object
code
required
string
message
required
string
error
object
code
Allowed value: unauthorized
WWW-Authenticate
required
string
Allowed value: Bearer

forbidden — the key lacks sync:write, or the window’s workspace is not the key’s.

object
error
required
object
code
required
string
message
required
string
error
object
code
Allowed value: forbidden

method_not_allowed — Allow names the method this route accepts.

object
error
required
object
code
required
string
message
required
string
error
object
code
Allowed value: method_not_allowed
Allow
required
string
Allowed value: POST

lease_lost, idempotency_conflict (the key was used for a different window), window_in_progress (another key owns a live lease for the exact window), or publication_rejected.

object
error
required
object
code
required
string
message
required
string
error
object
code
Allowed values: lease_lost idempotency_conflict window_in_progress publication_rejected

request_too_large — REST bodies are capped at 4 KiB.

object
error
required
object
code
required
string
message
required
string
error
object
code
Allowed value: request_too_large

unsupported_media_type unless the body is application/json, or unsupported_encoding for any Content-Encoding other than identity. Both are the gateway’s own; json_required is the same refusal raised by the sync service and passed through, and is classified here so that it cannot reach a caller as an unclassified failure.

object
error
required
object
code
required
string
message
required
string
error
object
code
Allowed values: unsupported_media_type unsupported_encoding json_required

invalid_lease_config — the sync service is misconfigured (its lease duration is outside the permitted range). Not retryable; it needs an operator.

Documented because the gateway classifies it, but the deployed sync service does not override the default lease duration, so it should not reach a caller.

object
error
required
object
code
required
string
message
required
string
error
object
code
Allowed value: invalid_lease_config

The run could not obtain trustworthy upstream data. Nothing is published, and any previous complete result is left intact. The code names which trust condition failed. This is the complete set — a 502 carries one of these and nothing else:

The provider could not be reached or would not answer: provider_auth_failed, provider_unavailable, provider_error.

The provider answered, but the report itself cannot be trusted: malformed_report, malformed_metadata, malformed_row, unexpected_schema, empty_report_reason, restricted_report, changing_report.

The report is not the whole of what was asked for, or does not agree with itself: incomplete_report, row_count_mismatch, row_count_limit, page_limit, duplicate_date.

The report could not be read out of the provider’s response: invalid_extraction, incomplete_extraction.

The raw evidence behind the run could not be written or could not be shown to be the evidence for this run: raw_commit_failed, raw_integrity_failure, raw_identity_mismatch, raw_missing.

The verified data could not be loaded into analytics storage: analytics_load_failed.

object
error
required
object
code
required
string
message
required
string
error
object
code
Allowed values: provider_auth_failed provider_unavailable provider_error malformed_report malformed_metadata empty_report_reason restricted_report unexpected_schema malformed_row changing_report row_count_limit row_count_mismatch incomplete_report duplicate_date page_limit invalid_extraction incomplete_extraction raw_integrity_failure raw_identity_mismatch raw_missing raw_commit_failed analytics_load_failed

sync_unavailable, auth_unavailable, credential_unavailable, credential_configuration_unavailable, credential_busy, provider_rate_limited, ledger_unavailable, analytics_load_unavailable or invalid_clickhouse_config. Retry with the same idempotency key.

object
error
required
object
code
required
string
message
required
string
error
object
code
Allowed values: sync_unavailable auth_unavailable credential_unavailable credential_configuration_unavailable credential_busy provider_rate_limited ledger_unavailable analytics_load_unavailable invalid_clickhouse_config