Content
Add an overview of the Admin - Content API here. This block is preserved across regenerations.
Endpoints
GET /api/v1/business-rules
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Filter by direction (upgrade, downgrade, cancellation, add_on, remove_add_on, retention_discount)
Filter by enforcement state
Paginated business rules
No content
GET /api/v1/business-rules HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
Paginated business rules
No content
Notes, examples, or caveats for GET /business-rules go here.
POST /api/v1/business-rules
isActive is REQUIRED — a business rule has no draft state, so an active rule is enforced from the moment it is written and there is no safe default to choose on the caller's behalf. isPlatformDefault cannot be set: it is cleared on every boot, so writing it would look applied and silently revert.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Required. True = enforced immediately.
Rule created; the response enforcement field states whether it is being enforced
No content
Validation error
POST /api/v1/business-rules HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 231
{
"name": "text",
"description": "text",
"direction": "upgrade",
"changeTiming": "immediate",
"timingValue": 1,
"timingUnit": "days",
"prorationType": "full",
"subscriptionState": "any",
"appliesToSurface": "any",
"blocksChange": true,
"isActive": true
}No content
A business rule is policy, not content. It decides whether a plan change is permitted at all (blocksChange), when it takes effect, how it prorates, and which subscription state and actor surface it governs.
isActive is required. Unlike journeys, pages and product sets, a rule has no draft state — no version to publish, no status to stage. Set it true and the rule is enforced from the moment it is written; set it false and it is authored but dormant. Neither is a safe default to pick on your behalf, so the API makes you say which you mean. The response carries an enforcement line restating what just happened.
isPlatformDefault cannot be set. Platform-default rules were retired; clearPlatformDefaultFlags() demotes any such row on every boot. Writing the flag would look applied and then silently revert at the next restart.
custom_delay and grace_period require both timingValue and timingUnit — without them the rule has no defined timing when the policy engine evaluates it.
DELETE /api/v1/business-rules/{id}
Deleting a rule REMOVES a policy. When the rule was an active hard block, that removes a guardrail — the audit entry records the rule's direction, enforcement state, blocking flag and attached journeys, since after deletion that is the only remaining evidence.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Deleted
No content
Not found
DELETE /api/v1/business-rules/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Deleting a rule removes a policy. When the rule was an active hard block (blocksChange: true), that is the removal of a guardrail, not just a tidy-up.
Because the row is gone afterwards, the audit entry records what the rule was doing — its direction, whether it was active, whether it was blocking, the subscription state it governed, and the journeys it was attached to. Check GET /business-rules/{id}/journeys first to see the blast radius.
GET /api/v1/business-rules/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Business rule
No content
Not found
GET /api/v1/business-rules/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /business-rules/{id} go here.
PATCH /api/v1/business-rules/{id}
The timing rule is checked against the MERGED result: patching changeTiming to custom_delay or grace_period without supplying a value and unit is refused, because the rule would otherwise have no defined timing when it is evaluated.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Rule updated
No content
Validation error
Not found
PATCH /api/v1/business-rules/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 109
{
"name": "text",
"changeTiming": "text",
"timingValue": 1,
"timingUnit": "text",
"blocksChange": true,
"isActive": true
}No content
The timing rule is validated against the merged result, not just the fields you send. Patching changeTiming to custom_delay or grace_period without also supplying a value and unit is refused, because the stored rule would otherwise be left with undefined timing.
Flipping isActive changes enforcement immediately in both directions — there is no publish step.
GET /api/v1/business-rules/{id}/journeys
The blast radius of a rule — read this before changing or deleting one.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Journeys using this rule
No content
Not found
GET /api/v1/business-rules/{id}/journeys HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /business-rules/{id}/journeys go here.
GET /api/v1/context/host-routes
Entry-point routing. Filterable by journeyId or pageId to answer "where do customers actually reach this?". The internal Cloudflare custom-hostname id is deliberately omitted.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Only routes targeting this journey
Only routes targeting this page
Paginated host routes
No content
GET /api/v1/context/host-routes HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
Paginated host routes
No content
The entry points — which hostname reaches which journey, step or page.
Filter by journeyId or pageId to answer "where do customers actually reach this?" after publishing something.
failureReason is included, because a route that is not serving is exactly the kind of thing an agent should be able to report back. The internal Cloudflare custom-hostname id is omitted; it is infrastructure plumbing with no authoring use.
GET /api/v1/context/integrations
Returns ONLY id, type, name, isActive and catalog-sync health. Credentials are never returned — not masked, not their key names — and config is not returned at all. This is an allowlist, so a column added to the integrations table in future stays invisible here until it is deliberately added.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Paginated integrations
No content
GET /api/v1/context/integrations HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
Paginated integrations
No content
Returns only an integration's identity and health: id, type, name, isActive, lastCatalogSyncAt, lastCatalogSyncStatus.
Credentials are never returned — not masked, not their key names. Neither is config.
This is an allowlist, and the distinction matters. The admin UI masks credentials by taking the whole row and overwriting one field; that approach exposes anything added to the table later, silently, the day it lands. Here nothing is returned unless it is named, so a new column stays invisible until someone deliberately exposes it.
What you get is what an authoring agent actually needs: enough to know which system a commerce action calls and whether it is usable.
GET /api/v1/context/integrations/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Integration
No content
Not found
GET /api/v1/context/integrations/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /context/integrations/{id} go here.
GET /api/v1/context/personas
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Paginated persona configurations
No content
GET /api/v1/context/personas HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
Paginated persona configurations
No content
Persona configurations describe the audiences a journey or page renders for, and their capabilities.
Read-only, like everything under /context. The context scope has exactly one verb and always will — an agent has to resolve what a journey references, and must never mutate it.
GET /api/v1/context/personas/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Persona configuration
No content
Not found
GET /api/v1/context/personas/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /context/personas/{id} go here.
GET /api/v1/custom-components
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Filter by editor context (payment, customer, portal, storefront, checkout, csr)
Paginated list of custom components
A custom UI component (code or template type) for the Puck editor
GET /api/v1/custom-components HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
Paginated list of custom components
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"displayName": "text",
"description": "text",
"componentType": "code",
"category": "text",
"editorContexts": [
"text"
],
"audienceRoles": [
"text"
],
"isActive": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for GET /custom-components go here.
POST /api/v1/custom-components
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Component created
A custom UI component (code or template type) for the Puck editor
Validation error
POST /api/v1/custom-components HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 117
{
"name": "text",
"displayName": "text",
"componentType": "code",
"code": "text",
"category": "text",
"editorContexts": [
"text"
]
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"displayName": "text",
"description": "text",
"componentType": "code",
"category": "text",
"editorContexts": [
"text"
],
"audienceRoles": [
"text"
],
"isActive": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for POST /custom-components go here.
DELETE /api/v1/custom-components/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Component deleted
No content
Not found
DELETE /api/v1/custom-components/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for DELETE /custom-components/{id} go here.
GET /api/v1/custom-components/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Component details
A custom UI component (code or template type) for the Puck editor
Not found
GET /api/v1/custom-components/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"displayName": "text",
"description": "text",
"componentType": "code",
"category": "text",
"editorContexts": [
"text"
],
"audienceRoles": [
"text"
],
"isActive": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for GET /custom-components/{id} go here.
PATCH /api/v1/custom-components/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Component updated
A custom UI component (code or template type) for the Puck editor
Not found
PATCH /api/v1/custom-components/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 66
{
"name": "text",
"displayName": "text",
"code": "text",
"isActive": true
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"displayName": "text",
"description": "text",
"componentType": "code",
"category": "text",
"editorContexts": [
"text"
],
"audienceRoles": [
"text"
],
"isActive": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for PATCH /custom-components/{id} go here.
GET /api/v1/journeys
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Filter by status (draft, active, archived)
Filter by journey type
Paginated list of journeys
No content
GET /api/v1/journeys HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
Paginated list of journeys
No content
Supports ?status= (draft, active, archived) and ?type= filters. An unrecognised status is a 400 rather than an empty list, so a typo cannot look like "no journeys".
POST /api/v1/journeys
A journey is always created as a draft. Publish it with POST /journeys/{id}/publish.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Journey created (status draft)
No content
Validation error
POST /api/v1/journeys HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 85
{
"name": "text",
"type": "text",
"description": "text",
"purpose": "text",
"audience": "text"
}No content
A journey is always created as a draft. Passing status: "active" is rejected rather than silently downgraded, because creating a live journey would bypass every publish gate.
Create the journey, add its steps, then publish it.
DELETE /api/v1/journeys/{id}
Deleting an ACTIVE journey takes it off the air and additionally requires journeys:publish.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Journey deleted
No content
Insufficient scope
Not found
DELETE /api/v1/journeys/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Deleting a draft or archived journey needs journeys:delete.
Deleting an active journey takes it off the air, so it additionally requires journeys:publish. Archive it first if your key only holds delete authority.
GET /api/v1/journeys/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Journey details
No content
Not found
GET /api/v1/journeys/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /journeys/{id} go here.
PATCH /api/v1/journeys/{id}
Changing status changes what is live and additionally requires journeys:publish — in either direction, since taking a live journey down matters as much as putting one up. A transition to active runs the publish gates and records a version.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Requires journeys:publish.
Journey updated
No content
Insufficient scope
Not found
PATCH /api/v1/journeys/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 53
{
"name": "text",
"description": "text",
"status": "draft"
}No content
Editing a journey's name, description or audience needs journeys:write.
Changing status is different. A journey's status is its live state, so a status transition additionally requires journeys:publish — in either direction. Deactivating a live journey is gated as tightly as activating one, because taking a journey off the air affects customers just as much as putting it up.
Re-sending the journey's current status is not a transition, so a client that submits the whole object on every save can keep editing a live journey with only journeys:write.
A transition to active runs the full publish validation and records a journey version — it behaves exactly like POST /journeys/{id}/publish, including its error responses.
POST /api/v1/journeys/{id}/publish
Runs the publish-time validation gates and records a journey version. A rejection returns the gate's own code — BROKEN_BRANCHING_TARGETS or UNSATISFIABLE_REQUIRED_ACTIONS — with its detail, so the problem can be fixed. Republishing an unchanged journey returns unchanged: true and mints no new version.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Journey published (or unchanged)
No content
Graph validation failed
Not found
A publish gate rejected the journey
POST /api/v1/journeys/{id}/publish HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Publishes the journey through the platform's publish-time validation. Four gates run, and a failure returns the gate's own error code so you can fix the specific problem:
BROKEN_BRANCHING_TARGETS (422)
A step branches to a target that no longer exists. The response lists brokenTargets.
UNSATISFIABLE_REQUIRED_ACTIONS (422)
A required commerce action has a hard-required field that nothing maps. The response lists errors.
graph validation (400)
The draft introduces a new cycle or unreachable step versus what is already published. Pre-existing issues do not block a republish.
Republishing a journey with no changes returns 200 with unchanged: true and does not mint a new version — check that flag rather than assuming a new version exists.
Non-blocking findings come back in warnings alongside a successful publish.
GET /api/v1/journeys/{id}/steps
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Paginated list of steps
No content
Not found
GET /api/v1/journeys/{id}/steps HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /journeys/{id}/steps go here.
POST /api/v1/journeys/{id}/steps
Draft-side: needs only journeys:write, and is invisible to live sessions until the journey is published. stepOrder is optional and appends when omitted.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
A page in the same tenant.
Step created
No content
Validation error
Not found
POST /api/v1/journeys/{id}/steps HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 67
{
"pageId": "text",
"label": "text",
"stepOrder": 1,
"branchingConfig": {}
}No content
Adding, editing and removing steps is draft-side and needs only journeys:write.
That is deliberate, not a gap. For a published journey the runtime serves the version snapshot frozen at publish time, so a step edit is invisible to live sessions until you publish again. journeys:delete means deleting the journey, not a step.
stepOrder is optional — omit it and the step is appended.
pageId must reference a page in the same tenant.
DELETE /api/v1/journeys/{id}/steps/{stepId}
Draft-side, so journeys:write — journeys:delete is for deleting the journey itself.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Step deleted
No content
Not found
DELETE /api/v1/journeys/{id}/steps/{stepId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for DELETE /journeys/{id}/steps/{stepId} go here.
GET /api/v1/journeys/{id}/steps/{stepId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Step
No content
Not found
GET /api/v1/journeys/{id}/steps/{stepId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /journeys/{id}/steps/{stepId} go here.
PATCH /api/v1/journeys/{id}/steps/{stepId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Step updated
No content
Not found
PATCH /api/v1/journeys/{id}/steps/{stepId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 69
{
"label": "text",
"pageId": "text",
"branchingConfig": {},
"disabled": true
}No content
Notes, examples, or caveats for PATCH /journeys/{id}/steps/{stepId} go here.
GET /api/v1/journeys/{id}/steps/{stepId}/actions
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Commerce actions in execution order
No content
Not found
GET /api/v1/journeys/{id}/steps/{stepId}/actions HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /journeys/{id}/steps/{stepId}/actions go here.
POST /api/v1/journeys/{id}/steps/{stepId}/actions
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Action created
No content
Validation error
Not found
POST /api/v1/journeys/{id}/steps/{stepId}/actions HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 94
{
"operationType": "text",
"executionMode": "blocking",
"integrationId": "text",
"fieldMapping": [
{}
]
}No content
Notes, examples, or caveats for POST /journeys/{id}/steps/{stepId}/actions go here.
DELETE /api/v1/journeys/{id}/steps/{stepId}/actions/{actionId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Action deleted
No content
Not found
DELETE /api/v1/journeys/{id}/steps/{stepId}/actions/{actionId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for DELETE /journeys/{id}/steps/{stepId}/actions/{actionId} go here.
PATCH /api/v1/journeys/{id}/steps/{stepId}/actions/{actionId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Action updated
No content
Not found
PATCH /api/v1/journeys/{id}/steps/{stepId}/actions/{actionId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 67
{
"executionMode": "text",
"integrationId": "text",
"fieldMapping": [
{}
]
}No content
Notes, examples, or caveats for PATCH /journeys/{id}/steps/{stepId}/actions/{actionId} go here.
POST /api/v1/journeys/{id}/steps/{stepId}/actions/reorder
Action order IS execution order, so the list must name every action on the step exactly once.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Actions reordered
No content
Invalid list
Not found
POST /api/v1/journeys/{id}/steps/{stepId}/actions/reorder HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 22
{
"actionIds": [
"text"
]
}No content
A step's action order is its execution order, so actionIds must name every action on the step exactly once. A partial list is refused — silently accepting one would change which action runs first.
POST /api/v1/journeys/{id}/steps/reorder
Must list every step exactly once. Rejected if the new order introduces a cycle or strands a step — non-retroactively, so a journey that already had a graph problem can still be rearranged toward a fix.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Steps reordered
No content
Invalid list or graph would break
Not found
POST /api/v1/journeys/{id}/steps/reorder HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 20
{
"stepIds": [
"text"
]
}No content
Supply stepIds naming every step of the journey exactly once. A partial or stale list is rejected rather than reordered into something you did not ask for.
The reorder is refused with journey_graph_invalid if the new order introduces a cycle or leaves a step unreachable. The check is non-retroactive: only problems the reorder itself introduces block it, so a journey that already had a graph issue can still be rearranged toward a fix. The response carries graphIssues with the offending step orders.
GET /api/v1/journeys/{id}/versions
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Paginated list of journey versions
No content
Not found
GET /api/v1/journeys/{id}/versions HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /journeys/{id}/versions go here.
GET /api/v1/journeys/{id}/versions/{versionId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Journey version
No content
Not found
GET /api/v1/journeys/{id}/versions/{versionId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /journeys/{id}/versions/{versionId} go here.
GET /api/v1/journeys/{journeyId}/business-rules
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Attached rules
No content
Not found
GET /api/v1/journeys/{journeyId}/business-rules HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /journeys/{journeyId}/business-rules go here.
POST /api/v1/journeys/{journeyId}/business-rules
Scoped as a rules:* operation — the rule is what is being applied. Both the journey and the rule must belong to the caller's tenant. A duplicate attachment returns 409 already_linked.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Attached
No content
Validation error
Already attached
POST /api/v1/journeys/{journeyId}/business-rules HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 25
{
"businessRuleId": "text"
}No content
Attaching a rule to a journey changes that journey's policy. It is scoped as a rules:* operation because the rule is what is being applied; the journey is still verified to belong to your tenant.
Both ends are re-checked under the tenant — a rule id from another tenant is refused rather than silently attaching a foreign policy. Attaching a rule that is already on the journey returns 409 already_linked rather than a raw database error.
DELETE /api/v1/journeys/{journeyId}/business-rules/{linkId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Detached
No content
Not found
DELETE /api/v1/journeys/{journeyId}/business-rules/{linkId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for DELETE /journeys/{journeyId}/business-rules/{linkId} go here.
GET /api/v1/pages
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Filter by page type
Paginated list of pages
A portal page, payment page, storefront page, or checkout page
GET /api/v1/pages HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
Paginated list of pages
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"slug": "text",
"type": "text",
"isActive": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for GET /pages go here.
POST /api/v1/pages
Setting pageContent publishes the page live and additionally requires the pages:publish scope; write draftPageContent and use POST /pages/{id}/publish instead.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Working draft. Safe to write with pages:write.
LIVE content. Requires pages:publish.
Page created
A portal page, payment page, storefront page, or checkout page
Validation error
POST /api/v1/pages HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 82
{
"name": "text",
"type": "text",
"slug": "text",
"draftPageContent": {},
"pageContent": {}
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"slug": "text",
"type": "text",
"isActive": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for POST /pages go here.
DELETE /api/v1/pages/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Page deleted
No content
Not found
DELETE /api/v1/pages/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for DELETE /pages/{id} go here.
GET /api/v1/pages/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Page details
A portal page, payment page, storefront page, or checkout page
Not found
GET /api/v1/pages/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"slug": "text",
"type": "text",
"isActive": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for GET /pages/{id} go here.
PATCH /api/v1/pages/{id}
Setting pageContent publishes the page live and additionally requires the pages:publish scope; write draftPageContent and use POST /pages/{id}/publish instead.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Working draft. Safe to write with pages:write.
LIVE content. Requires pages:publish.
Page updated
A portal page, payment page, storefront page, or checkout page
Not found
PATCH /api/v1/pages/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 68
{
"name": "text",
"slug": "text",
"draftPageContent": {},
"pageContent": {}
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"slug": "text",
"type": "text",
"isActive": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for PATCH /pages/{id} go here.
GET /api/v1/pages/{id}/manifest
What this page sells — product set, persona config and resolved commerce manifest. Read-only context for an agent editing the page.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Page commerce manifest
No content
Not found
GET /api/v1/pages/{id}/manifest HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /pages/{id}/manifest go here.
POST /api/v1/pages/{id}/publish
Copies draftPageContent onto pageContent and records a published version. The explicit form of what setting pageContent used to do implicitly.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Page published
A portal page, payment page, storefront page, or checkout page
Not found
No draft content to publish
POST /api/v1/pages/{id}/publish HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"slug": "text",
"type": "text",
"isActive": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for POST /pages/{id}/publish go here.
GET /api/v1/pages/{id}/versions
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Paginated list of versions
No content
Not found
GET /api/v1/pages/{id}/versions HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /pages/{id}/versions go here.
GET /api/v1/pages/{id}/versions/{versionId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Version details
No content
Not found
GET /api/v1/pages/{id}/versions/{versionId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /pages/{id}/versions/{versionId} go here.
POST /api/v1/pages/{id}/versions/{versionId}/restore
Restores into draftPageContent, never directly to live — so rolling back what is published stays a deliberate restore-then-publish. Requires pages:write only.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Draft restored
A portal page, payment page, storefront page, or checkout page
Not found
POST /api/v1/pages/{id}/versions/{versionId}/restore HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"slug": "text",
"type": "text",
"isActive": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for POST /pages/{id}/versions/{versionId}/restore go here.
GET /api/v1/product-sets
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Filter by status (draft, active, archived)
Paginated product sets
No content
GET /api/v1/product-sets HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
Paginated product sets
No content
Notes, examples, or caveats for GET /product-sets go here.
POST /api/v1/product-sets
Always created as a draft. Activate it with PATCH once its items are in place — activation runs the timing anchor rule and needs productsets:publish.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Product set created (status draft)
No content
Validation error
POST /api/v1/product-sets HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 69
{
"name": "text",
"description": "text",
"carryQuantityOnBaseChange": true
}No content
Product sets are always created as drafts. Passing status: "active" is rejected rather than downgraded, because a set born active would skip the activation timing gate entirely.
The normal shape is: create the set → add its items → PATCH status to active with a key holding productsets:publish.
DELETE /api/v1/product-sets/{id}
Deleting an ACTIVE set withdraws it from customers and additionally requires productsets:publish.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Deleted
No content
Insufficient scope
Not found
DELETE /api/v1/product-sets/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for DELETE /product-sets/{id} go here.
GET /api/v1/product-sets/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Product set
No content
Not found
GET /api/v1/product-sets/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /product-sets/{id} go here.
PATCH /api/v1/product-sets/{id}
An ACTIVE set resolves for customers and has no version snapshot, so any edit to it — and every status transition in either direction — additionally requires productsets:publish. Activating runs the §1.5 anchor rule and returns product_set_timing_invalid if no line uses same-as-order timing.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Requires productsets:publish.
Updated
No content
Timing/validation error
Insufficient scope
Not found
PATCH /api/v1/product-sets/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 53
{
"name": "text",
"description": "text",
"status": "draft"
}No content
A product set is the strictest surface in the API, for a reason worth understanding.
Unlike a journey or a page, a product set has no version snapshot. A journey freezes its steps at publish time, so editing the draft cannot reach a running session. A product set is resolved straight from its live rows — so if the set is active, an edit is in front of customers immediately.
Accordingly:
The set is…
productsets:write can edit it?
draft
yes
archived
yes
active
no — needs productsets:publish
A status transition needs productsets:publish in either direction, since deactivating a live set withdraws it from customers just as surely as activating one exposes it.
Activating also runs the §1.5 anchor rule: at least one line must use same_as_order timing, so something bills or activates immediately. A set that fails it comes back 400 product_set_timing_invalid with the specific errors in configErrors. Draft edits are allowed to defer this — activation is where it bites.
GET /api/v1/product-sets/{id}/bundles
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Bundles with their members
No content
Not found
GET /api/v1/product-sets/{id}/bundles HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /product-sets/{id}/bundles go here.
POST /api/v1/product-sets/{id}/bundles
A bundle is one FACE entry (the card the customer sees) plus one or more MEMBER entries added silently when the face is selected. The face may not be a member of its own bundle, and a bundle must have at least one member.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Bundle created
No content
Validation error
POST /api/v1/product-sets/{id}/bundles HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 60
{
"name": "text",
"faceItemId": "text",
"memberItemIds": [
"text"
]
}No content
A bundle is a composition unit inside a set: one face entry (the card the customer actually sees) plus one or more member entries that are added silently to the order when the face is selected.
Two shapes are refused: a face that is also a member of its own bundle, and a bundle with no members at all.
Bundles are distinct from the classification-driven groups in the editor — groups are taxonomy that organize the card list, bundles compose sellable units. An entry keeps its classification while being a bundle member; the two axes are orthogonal.
DELETE /api/v1/product-sets/{id}/bundles/{bundleId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Deleted
No content
Not found
DELETE /api/v1/product-sets/{id}/bundles/{bundleId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for DELETE /product-sets/{id}/bundles/{bundleId} go here.
PATCH /api/v1/product-sets/{id}/bundles/{bundleId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Bundle updated
No content
Validation error
Not found
PATCH /api/v1/product-sets/{id}/bundles/{bundleId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 60
{
"name": "text",
"faceItemId": "text",
"memberItemIds": [
"text"
]
}No content
Notes, examples, or caveats for PATCH /product-sets/{id}/bundles/{bundleId} go here.
GET /api/v1/product-sets/{id}/dependencies
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Dependencies
No content
Not found
GET /api/v1/product-sets/{id}/dependencies HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for GET /product-sets/{id}/dependencies go here.
POST /api/v1/product-sets/{id}/dependencies
Both ends must be items of THIS set, and an item cannot depend on itself.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Dependency created
No content
Validation error
POST /api/v1/product-sets/{id}/dependencies HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 73
{
"sourceItemId": "text",
"targetItemId": "text",
"dependencyType": "requires"
}No content
Both sourceItemId and targetItemId must be items of this set — a dependency pointing outside it would be unresolvable at runtime — and an item cannot depend on itself.
DELETE /api/v1/product-sets/{id}/dependencies/{depId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Deleted
No content
Not found
DELETE /api/v1/product-sets/{id}/dependencies/{depId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for DELETE /product-sets/{id}/dependencies/{depId} go here.
GET /api/v1/product-sets/{id}/items
Each item carries a derived orderGroup (default or own), read from metadata.orderGroup with any unrecognised value reported as default, alongside its effectiveDateTiming.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Paginated items
No content
Not found
GET /api/v1/product-sets/{id}/items HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Each item includes its effectiveDateTiming and a derived orderGroup ("default" or "own") — see POST /product-sets/{id}/items for what they do.
POST /api/v1/product-sets/{id}/items
productId must reference a product in the same tenant. On an ACTIVE set this requires productsets:publish.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
How the line is booked when a journey places the order. own books it as its own order action (an AddProduct) in the same order and subscription; default books it with the other lines. Honored only by journeys whose create_order action has honorOrderGrouping on. Stored in the item's metadata.orderGroup and merged there server-side, so setting it never replaces other metadata keys. Defaults to default.
When the line starts, counted from the order date. same_as_order (the default) starts it on the order date; set_period starts it value (1–120) unit later. Applied at checkout only when the create_order action has honorActivationOffsets on. On an ACTIVE set at least one line must stay same_as_order (the anchor rule); a write that breaks it returns 400 product_set_timing_invalid.
Item added. Items are returned with a derived orderGroup, and configWarnings when the set's lines resolve to more than two activation dates.
No content
Validation error, or product_set_timing_invalid when the write would leave an active set with no same-as-order line
Set is active
POST /api/v1/product-sets/{id}/items HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 163
{
"productId": "text",
"planId": "text",
"classification": "base",
"groupName": "text",
"sortOrder": 1,
"orderGroup": "default",
"effectiveDateTiming": {
"mode": "same_as_order"
}
}No content
productId must reference a product in the same tenant.
If the set is active, adding an item requires productsets:publish — the item is purchasable the moment it lands, since a product set resolves from its live rows with no draft buffer.
How the line is booked. Two optional fields control how this line lands in the order when a journey checks out:
orderGroup
"default" · "own"
"default"
"own" books the line as its own order action (an Add Product) within the same order and subscription. Takes effect only when the journey's create_order action has honorOrderGrouping on.
effectiveDateTiming
{"mode":"same_as_order"} · {"mode":"set_period","value":1–120,"unit":"days"|"months"|"years"}
same_as_order
When the line starts, counted from the order date. Applied only when the create_order action has honorActivationOffsets on.
orderGroupis stored in the item'smetadata.orderGroupand merged in on the server, so sending it never replaces othermetadatakeys such asvisibility. Every item response carries the derivedorderGroup.On an
activeset, at least one line must staysame_as_order. A write that breaks this is refused with400 product_set_timing_invalid, the same error activation returns. A draft set may pass through that state while you assemble it.When the set's lines resolve to more than two distinct start dates, the response includes
configWarnings.
See Booking a Line as Its Own Order Action for how the order is built from these fields.
DELETE /api/v1/product-sets/{id}/items/{itemId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Item removed
No content
Set is active
Not found
DELETE /api/v1/product-sets/{id}/items/{itemId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for DELETE /product-sets/{id}/items/{itemId} go here.
PATCH /api/v1/product-sets/{id}/items/{itemId}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
How the line is booked when a journey places the order. own books it as its own order action (an AddProduct) in the same order and subscription; default books it with the other lines. Honored only by journeys whose create_order action has honorOrderGrouping on. Stored in the item's metadata.orderGroup and merged there server-side, so setting it never replaces other metadata keys. Defaults to default.
When the line starts, counted from the order date. same_as_order (the default) starts it on the order date; set_period starts it value (1–120) unit later. Applied at checkout only when the create_order action has honorActivationOffsets on. On an ACTIVE set at least one line must stay same_as_order (the anchor rule); a write that breaks it returns 400 product_set_timing_invalid.
Item updated. Returned with a derived orderGroup, and configWarnings when relevant.
No content
Validation error, or product_set_timing_invalid when the change would leave an active set with no same-as-order line
Set is active
Not found
PATCH /api/v1/product-sets/{id}/items/{itemId} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 128
{
"classification": "text",
"groupName": "text",
"sortOrder": 1,
"orderGroup": "default",
"effectiveDateTiming": {
"mode": "same_as_order"
}
}No content
Send only the fields you are changing. orderGroup and effectiveDateTiming behave as described under POST /product-sets/{id}/items: orderGroup merges into the stored metadata, and a timing change that would leave an active set with no same_as_order line is refused with 400 product_set_timing_invalid.
Editing an item on an active set requires productsets:publish.
POST /api/v1/product-sets/{id}/items/reorder
Sort order drives card order in every consumer, so itemIds must list every item exactly once.
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Reordered
No content
Invalid list
POST /api/v1/product-sets/{id}/items/reorder HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 20
{
"itemIds": [
"text"
]
}No content
Notes, examples, or caveats for POST /product-sets/{id}/items/reorder go here.
GET /api/v1/templates
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Max items to return (1–100, default 20)
20Number of items to skip (default 0)
0Filter by page type
Paginated list of page templates
A reusable page template for the editor
GET /api/v1/templates HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
Paginated list of page templates
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"description": "text",
"pageType": "text",
"thumbnail": "text",
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for GET /templates go here.
POST /api/v1/templates
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Template created
A reusable page template for the editor
Validation error
POST /api/v1/templates HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 71
{
"name": "text",
"description": "text",
"pageType": "text",
"pageContent": {}
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"description": "text",
"pageType": "text",
"thumbnail": "text",
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for POST /templates go here.
DELETE /api/v1/templates/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Template deleted
No content
System template — cannot delete
Not found
DELETE /api/v1/templates/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
No content
Notes, examples, or caveats for DELETE /templates/{id} go here.
GET /api/v1/templates/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Template details
A reusable page template for the editor
Not found
GET /api/v1/templates/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"description": "text",
"pageType": "text",
"thumbnail": "text",
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for GET /templates/{id} go here.
PATCH /api/v1/templates/{id}
Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.
Template updated
A reusable page template for the editor
System template — cannot modify
Not found
PATCH /api/v1/templates/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 69
{
"name": "text",
"description": "text",
"pageContent": {},
"isActive": true
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"description": "text",
"pageType": "text",
"thumbnail": "text",
"createdAt": "2026-01-01T00:00:00.000Z"
}Notes, examples, or caveats for PATCH /templates/{id} go here.
Last updated
Was this helpful?
