customer_map
GET /customer-map
Get the current customer map
The customer map of the credential's project and environment: the slot that feeds it, the current map and the state of its updates, computed when read. Requires the read scope; an application principal is refused (application_operation_not_allowed). The slot. A candidate is active, has an active bundle, runs in mode: live, serves a sequence-model bundle, and its purpose is one the caller may use (the purpose gate of GET /slots/\{slot\}/exports). Without slot (an empty slot included), the map's stored slot (its settings, slot_choice admin or automatic as stored) is read while it is a candidate; otherwise the server chooses among the candidates (slot_choice: automatic), preferring, in order: a slot with a succeeded map that carries a segment column and is not held, over its whole history (a batch_only one first, then the newest such map); a slot whose current segment registry was built on its active bundle; a batch_only slot; the newest activation; the lowest slot_id. With no candidate, slot is null, slot_choice is none and state is no_model. With slot (a slot_ id or the slot's name), the map of that slot is read (slot_choice: requested): another project's or environment's slot, or a missing one, is 404 not_found, and a slot whose purpose the caller may not use is 403 permission_denied (purpose_not_allowed), as on GET /slots/\{slot\}/exports. The current map, decided over the slot's whole history: while a pin is active, the pinned edition; otherwise the newest succeeded map edition (a run of the customer map's own recipe) whose verdict is shown; failing that, the newest succeeded projection_2d export that carries a segment column and is not held; failing that, the newest succeeded one that is not held. A held map is never current. A map with no recorded verdict (not_recorded: a manual projection, or a map drawn before verdicts were recorded) is current only while no shown edition exists. Each step names the export kind and status, so state-snapshot exports never hide a map. updating is the newest queued or running projection_2d export that is newer than current, still within its run deadline (4 hours after it started, or after it was queued, plus 5 minutes; a run past that is never reported), and could become current: an edition once the slot has any edition; otherwise a run requested with a segment column while current is grouped, or any run. last_failure is the newest failed projection_2d export newer than current, an edition once the slot has any edition. Load an edition's file with GET /slots/\{slot\}/exports/\{export_id\}. The schedule and the pin (schedule, pin) describe the map's stored settings. They are shown only when the slot read is the map's EFFECTIVE slot (the slot an Admin chose; for an automatic map, the stored slot while it is a candidate, else the unrestricted automatic choice) and the caller may use the stored slot's purpose; otherwise both are null, so nothing of a barred slot is revealed (as on GET /customer-map/settings). A pin applies only while its pinned export is on the effective slot: a pin left on a slot the map no longer follows is never shown, skips no scheduled update and refuses no Update now. latest_change is the current edition's recorded change, null when it recorded none. States, the first that applies: no_model (no slot, or the slot serves no model and has no map); no_map (no map yet); first_map_pending (the first map is being drawn); pinned (a pin is active); updating (a newer map is being drawn while current stays readable); failed (the newest finished edition failed; last_failure names it); held (the newest finished edition was held; current stays the previous map); out_of_date (a scheduled update is overdue and has not started); paused and on_request (the settings stop scheduled updates); needs_admin (no credential to run scheduled updates as, or it may not use the map slot's purpose); up_to_date otherwise.
Operation ID: getCustomerMap · Service: serving-api
Authentication
apiKey(http (bearer)) — Project API key (003 §2):tsk_live_…ortsk_test_…inAuthorization: Bearer. Scoped to exactly one project + environment; scopes are a subset ofingest,read,admin. Keys are stored hashed and shown once at creation.consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slot | query | no | string | Read the map of this slot instead of the one the server chooses: the slot id (slot_ ULID) or the slot's name. |
Responses
| Status | Schema | Description |
|---|---|---|
200 | CustomerMap | The customer map. |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
GET /customer-map/editions
List the editions of the customer map
The history of the customer map of the resolved project and environment, newest first with cursor pagination (003 §1, at most 50 per page): every edition of the slot getCustomerMap reads for the caller (a projection_2d export the schedule or Update now started), with its change against the edition's reference (the map shown when the edition was drawn) and its layout and stability figures. The pinned export is listed too whenever it is not itself an edition, in created_at order like any other entry and counted within limit. Editions of any other slot are not listed. The slot is resolved for the caller exactly as getCustomerMap resolves it (the purpose gate of GET /slots/\{slot\}/exports filters; it never refuses): with no slot the caller may use, the page is empty. Held editions are listed with verdict: held; an edition drawn before editions recorded a verdict or a layout reads not_recorded, never a guessed value. An entry's change and stability are null when the edition recorded none (still running, failed, or drawn before the map recorded them). Editions publish export.completed / export.failed like any projection, with the edition-only keys layout, verdict, verdict_basis and alignment (and changes and stability, written on every edition and null when nothing could be compared) in a succeeded edition's data.metadata, and meter nothing. Each edition's file is read with getSlotExport. Requires the read scope; application principals are refused.
Operation ID: listCustomerMapEditions · Service: serving-api
Authentication
apiKey(http (bearer)) — Project API key (003 §2):tsk_live_…ortsk_test_…inAuthorization: Bearer. Scoped to exactly one project + environment; scopes are a subset ofingest,read,admin. Keys are stored hashed and shown once at creation.consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
cursor | query | no | string | Opaque pagination cursor from a previous response's next_cursor. |
limit | query | no | integer | Page size in customer map editions (cursor pagination, 003 §1). Maximum 50: each entry carries its change block of up to 257 groups. |
Pagination
Cursor pagination (003 §1): pass limit (max 200) and cursor; the
response is the pagination envelope — data plus next_cursor
(null on the last page).
Responses
| Status | Schema | Description |
|---|---|---|
200 | CustomerMapEditionPage | Page of map editions, newest first. |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
GET /customer-map/settings
Get the customer map settings
The customer map settings of the resolved project and environment: how often the map updates, when, in which time zone, the cooldown after an update, any pin and which slot the map follows. Reading writes nothing: before an Admin or the platform has stored settings, the defaults are returned (nightly at 03:00 UTC, cooldown 15 minutes, automatic slot, no pin) with created_at and updated_at null. runs_as says whose credential scheduled editions run as; none means scheduled editions wait until an Admin saves these settings. slot: with slot_choice: admin, the Admin's stored slot, shown while the caller may use its purpose even after it stops qualifying (next_run_at is then null; a save naming it, or Update now, answers slot_not_eligible or model_family_not_supported). With slot_choice: automatic, resolved for the caller as getCustomerMap resolves it: the stored slot while it is a candidate the caller may use (the purpose gate of GET /slots/\{slot\}/exports), otherwise the automatic choice among the slots the caller may use, otherwise null. This filters; it never refuses. When the stored slot is barred to the caller, pin and next_run_at are null and colours is empty, so nothing of that slot is revealed or can be inferred. The pin and the schedule apply on the map's effective slot only (see getCustomerMap). With no settings stored, the defaults are shown. runs_as and next_run_at describe a schedule only when the project and environment has a succeeded grouped map (one carrying a segment column), whose default settings the platform stores and schedules by itself, seeding map_requester; otherwise runs_as is none and next_run_at is null, and nothing is scheduled until an Admin saves the settings. Requires the read scope; application principals are refused.
Operation ID: getCustomerMapSettings · Service: serving-api
Authentication
apiKey(http (bearer)) — Project API key (003 §2):tsk_live_…ortsk_test_…inAuthorization: Bearer. Scoped to exactly one project + environment; scopes are a subset ofingest,read,admin. Keys are stored hashed and shown once at creation.consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Responses
| Status | Schema | Description |
|---|---|---|
200 | CustomerMapSettings | The customer map settings. |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
PUT /customer-map/settings
Replace the customer map settings
Replaces the customer map settings of the resolved project and environment and, in the same transaction, the map's customer_map tick schedule. frequency selects the cadence: nightly, weekly (weekday, 1 = Monday to 7 = Sunday, required) and monthly (day_of_month, 1 to 28, required) update at local_time (HH:MM, default 03:00) in time_zone (an IANA name such as Europe/London; UTC by default), following daylight-saving changes; custom updates every every_hours hours (1 to 168, required); on_request updates only on refreshCustomerMap. paused: true stops scheduled editions without losing the cadence. A field that does not apply to the chosen frequency must be omitted or null; out-of-range values, unknown or host-local time zones (localtime, posix/…, right/…) and unknown fields are 400 invalid_argument naming the field. cooldown_minutes (0 to 1440) is the wait after a succeeded edition before the next refreshCustomerMap (at least 15 minutes for non-Admin callers). Concurrent saves. expected_updated_at is the updated_at the caller last read (null: no settings are stored yet); when it no longer matches, the save is 400 failed_precondition version_mismatch and nothing changes. Omitted, no check is made; the console always sends it. The slot. slot_id chooses the slot the map follows (null: automatic, the server's one-map rule). A slot of another project or environment, or one that does not exist, is 404 not_found; a slot the map cannot follow (not active and live, no active bundle) is 400 failed_precondition (slot_not_eligible), an event-model slot 400 failed_precondition (model_family_not_supported), and a slot whose purpose the caller may not use 403 permission_denied (purpose_not_allowed). Changing the slot while a pin of another slot is active is 400 failed_precondition pin_other_slot: remove the pin in the same request (pin: null) or first. Two more saves are 403 permission_denied (purpose_not_allowed): slot_id: null (automatic) while the stored slot is one whose purpose the caller may not use (so an Admin cannot leave a barred slot that way); and removing an active pin, or leaving it behind with a slot change, when the caller may not use the pinned slot's purpose. The pin. pin keeps one edition as the current map until pin.until, which must lie after now and at most 90 days ahead (otherwise 400 invalid_argument on pin.until). pin.export_id names a succeeded projection_2d export of the slot the map follows after this request whose colour columns are recipe-safe (scores and segment_id only); omitted or null, the current map is pinned. An export that does not exist, or belongs to another project or environment, is 404 not_found; one of this project and environment that is of another slot, did not succeed, is not projection_2d, or is coloured by any other column (event attributes above all) is 400 failed_precondition pin_export_not_eligible, so the Customer map never shows Members and Viewers a column outside the map recipe; no current map to pin is 400 failed_precondition no_map. While a pin on the map's effective slot is active, scheduled editions are skipped and refreshCustomerMap is refused (map_pinned); a pin left on a slot the map no longer follows applies nowhere. pin: null removes a pin. Run identity. Saving makes the caller the credential scheduled editions run as (runs_as: admin): an Admin session, or an API key with the admin scope (a standing credential like any other, and a deliberate, documented reading of ruling 3, which names the Admin). The stored identity is re-validated before every scheduled edition: a saver later removed, revoked, no longer holding customer_map.settings.put, or no longer allowed to use the map slot's purpose no longer qualifies, and the map waits for an Admin (runs_as: none, state needs_admin). Scheduled editions, like Update now ones, publish export.completed / export.failed with data.kind: projection_2d and meter nothing; a succeeded edition's data.metadata carries the edition-only keys layout, verdict, verdict_basis and alignment, and changes and stability (written on every edition, null when nothing could be compared). The change is audited as customer_map.settings.update with the values before and after; a session or API key refused by the role or key-scope check or the purpose gate is audited with outcome denied (an application principal and a credential of a suspended project are refused before any tenancy resolves and leave no row). Admins only; API keys need the admin scope; application principals are refused.
Operation ID: putCustomerMapSettings · Service: serving-api
Authentication
apiKey(http (bearer)) — Project API key (003 §2):tsk_live_…ortsk_test_…inAuthorization: Bearer. Scoped to exactly one project + environment; scopes are a subset ofingest,read,admin. Keys are stored hashed and shown once at creation.consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Request body
Responses
| Status | Schema | Description |
|---|---|---|
200 | CustomerMapSettings | The stored customer map settings. |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
POST /customer-map:refresh
Update the customer map now
Starts a new edition of the project's customer map for the resolved environment ("Update now", CM-06). The edition is a projection_2d export of the map's slot on the fixed map recipe: every customer up to 200,000, seed 42 and the map's own colour columns, never a column coloured by event attributes. The request takes no parameters: no body, an empty JSON object or a JSON null are the same request (also for Idempotency-Key); any field is 400 invalid_argument, so no caller chooses columns, sample size or seed. Checks, in this order; the first that fails answers. (1) Authorization: Members and Admins may call it, API keys need the admin scope, application principals are refused (403 permission_denied). (2) The map's STORED slot, never a choice made for the caller. With slot_choice: admin, the slot the Admin chose, and only it: one that no longer qualifies is 400 failed_precondition with its reason (slot_not_eligible: missing, not active and live, or without an active bundle; model_family_not_supported: an event model), never a silent switch. With slot_choice: automatic, or no settings stored, the stored slot while it is still a candidate, else the slot getCustomerMap chooses for an unrestricted view; none is 400 failed_precondition no_model. (3) The slot purpose gate of GET /slots/\{slot\}/exports on that slot: a caller who may not use its purpose gets 403 permission_denied (purpose_not_allowed, WP-V12) and learns nothing else of the map (not its pin, not an edition in flight); the reads filter by purpose, this write refuses. (4) A pin on that slot: 400 failed_precondition map_pinned, with until. (5) One edition at a time: while an edition of the map's slot is queued or running, the call starts nothing and answers 202 with that edition (its trigger says who started it; its requester stays the one who started it). While an edition started before a slot change is still in flight on the PREVIOUS slot, the call is 400 failed_precondition update_in_progress with retry_after; it never names nor joins that edition. An edition counts as in flight until it finishes or reaches the job deadline (4 hours) plus a 5-minute grace. (6) A held map: while the newest edition was held for groups_missing and the slot's segment build has not changed since, 400 failed_precondition groups_missing with export_id naming the held edition. (7) The cooldown and the backoff: 400 failed_precondition cooldown with retry_after (RFC 3339 UTC) until the LATER of two bounds: the newest succeeded edition's finish plus the effective cooldown, and, for a non-Admin caller, the newest failed edition's finish plus min(effective cooldown, 2^n) minutes after n consecutive failed editions. (8) The daily cap, 400 failed_precondition daily_cap with retry_after: once 24 editions started by non-Admin callers began in the past 24 hours. (9) The edition is created. Every details[0] is \{type: precondition_failure, reason, ...\}. Checks (4) to (8) are answered without waiting on another call; when concurrent calls race for the insert, the call that loses joins the edition the other started (202), or, if that edition is not yet visible, answers 503 unavailable (update_in_progress) with retry_after_seconds and a Retry-After header. Every condition is checked again before the insert. A transient failure to read the map's settings answers 503 unavailable (settings_unavailable) with retry_after_seconds; nothing is stored. Admin and non-Admin callers. An Admin caller is a console session that holds customer_map.settings.put in the project (the built-in Admin and Owner, or a custom role granting it); every API key and every other session is a non-Admin caller. The effective cooldown is the map's cooldown_minutes for an Admin caller and at least 15 minutes for a non-Admin caller (a cooldown of 0 applies to Admins only). A failed edition starts no cooldown of its own: an Admin may retry at once after a failure, but never before the cooldown after the newest success has passed. The daily cap counts editions started by non-Admin callers only. These limits, one edition at a time and the pin are the only cost controls: map editions meter nothing and never appear in usage. Pausing the map or setting it to on_request stops scheduled editions only; Update now still runs. A pin stops both. Each edition is aligned and compared to the current map (the pinned one, or the newest shown), never to a held edition. The edition runs as the caller: its requester is the calling user or API key, never unset, so the job applies the caller's purposes. The call is audited as customer_map.refresh: a started edition and a joined in-flight one (details.joined: true, naming it) with outcome success; a session or API key refused by the role or key-scope check of (1), or by the purpose gate of (3), with outcome denied. An application principal and a credential of a suspended project are refused before any tenancy resolves, as on every operation, and leave no row. Map editions emit no export_rows usage, publish export.completed / export.failed with data.kind: projection_2d like any projection, and are read with getSlotExport. A succeeded edition's data.metadata carries the edition-only keys layout, verdict, verdict_basis and alignment (CM-10a) and changes and stability (CM-10b; written on every edition, null when nothing could be compared), which no manual projection carries; receivers can tell editions apart by them, and listCustomerMapEditions lists them. An Idempotency-Key replays the first answer within its 24 h window.
Operation ID: refreshCustomerMap · Service: serving-api
Authentication
apiKey(http (bearer)) — Project API key (003 §2):tsk_live_…ortsk_test_…inAuthorization: Bearer. Scoped to exactly one project + environment; scopes are a subset ofingest,read,admin. Keys are stored hashed and shown once at creation.consoleSession(http (bearer)) — Console session (003 §2): Identity Platform JWT. Data-plane calls addX-Tessera-Project+X-Tessera-Environmentheaders, validated against org membership.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
Idempotency-Key | header | no | string | Idempotency key accepted by all POSTs (003 §1): 24 h dedup window, keyed per project. POSTs that are reads (batchSlotScores, scoreSlotEvent, deriveSlotBands, validateSourceRawPreset, sampleSource, watchEventFeedHeads and the preview operations: previewSourceMapping, previewCatalogMapping, previewLabel, previewPatternLabel, previewMarker, previewDatasetEligibility, previewSlotAudience, previewSharedCheckpointImport, previewSlotAtlasInquiry) accept the key but never replay a stored response: a retry with the same key is executed again (and metered again) against current data. A stored response that names an entity is removed when that entity is erased. A key that already answered answers only a retry of the request that stored its response: the same caller, environment, operation, path, query, scoping headers and body (a JSON body by its content, a gzip body by its inflated content). The same key with any other request is 409 already_exists with details[0].reason idempotency_key_reused, and that request is not run. The window holds no in-flight marker: two first requests sent at once can both run. A response stored by a release before this rule cannot be matched to its request and is refused the same way until it expires; send the request again with a new key. A body over 8 MiB (ingest: over its 5 MiB request limit) is run and its response is not stored. The ingest batch (POST /events) is the exception, except for an application's credentials: under a key that answered another batch it runs again, uncached, and its events' ids deduplicate them; so it does when its stored response cannot be checked. The operations that return a one-time secret store their response sealed: the stored copy opens only for the same key and credential, and one that cannot be opened is 409 idempotency_key_reused. While the server cannot check a stored response (it cannot read the key that checks it, for one), the request is 503 unavailable with Retry-After: retry with the same key. An operation whose handler claims the key itself answers the same 503, before it runs, while the key-hash pepper cannot be read; any other request sent with a key runs meanwhile, and its response is not stored. |
Idempotency
This operation accepts an Idempotency-Key header (003 §1): within
24 hours, keyed per project and caller, a retry of the same request
gets the first response, and the same key with another request is
409 already_exists (idempotency_key_reused). See the
Idempotency-Key parameter for the exceptions.
Request body
CustomerMapRefreshRequest (optional)
Responses
| Status | Schema | Description |
|---|---|---|
202 | CustomerMapEdition | The edition this call started, or the edition already queued or running. |
default | ErrorEnvelope | Error response (003 §1). Every non-2xx response uses this envelope; the HTTP status matches error.code. Rate-limited requests get 429 resource_exhausted with retry_after_seconds and a Retry-After header; the X-RateLimit-* headers ride on EVERY response, success or error (003 §1; plan-driven per API key + endpoint class — WP-B2). A 503 unavailable carries retry_after_seconds too for a lock-wait timeout (SQLSTATE 55P03), a rule preview at capacity (preview_capacity_exhausted), or a label preview during which the erasure of every entity holding its censor clock began (label_preview_clock_entity_erased): how long to wait before retrying. |
Errors
Every non-2xx response uses the 003 §1 error envelope; error.request_id
matches the X-Request-Id response header, and the HTTP status always
matches error.code:
{
"error": {
"code": "invalid_argument",
"details": [
{
"type": "field_violation"
}
],
"message": "human-readable",
"request_id": "req_01hxample"
}
}
Closed error-code set (003 §1): invalid_argument, unauthenticated, permission_denied, not_found, already_exists, failed_precondition, resource_exhausted, internal, unavailable.
resource_exhausted responses (HTTP 429) additionally carry
retry_after_seconds. See ErrorEnvelope.