developer

Generated OpenAPI reference

API for managing A/B testing experiments, variations, goals, webhooks, and screenshots.

Assignments

GET

Get deterministic server-side assignments

/assign

Parameters

  • shop_id in query required
  • user_id in query required
  • url in query
  • environment in query
  • experiments in query

Responses

  • 200 Assignments and program cohort returned
  • 400 Invalid request, including a customer identifier supplied in the query string instead of a POST body.
  • 401
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/assign \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Get deterministic assignments with commerce proof inputs

/assign

Request body

{
  shop_id: string
  user_id?: string
  logged_in_customer_id?: string
  customer_id?: string
  decision_use?: "aggregate" | "individual"
  url?: string (uri)
  environment?: string
  experiments?: string[]
  cart_token?: string
  persist_function_handoff?: boolean
  exclusion_group_selections?: object[]
}

Responses

  • 200 Assignments, program cohort, and commerce authorization returned
  • 400
  • 401
  • 403 A logged-in customer assignment was requested for an individual-level decision.
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/assign \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "shop_id": "example_shop_id"
}'

Runtime

POST

Verify a signed cross-domain bucketing handover token

/handover/verify

Worker runtime endpoint. Verifies the token signature, expiry, and shop binding without requiring ingest credentials.

Parameters

  • X-Drip-Shop in header required

Request body

{
  verifyToken: string
}

Responses

  • 200 Verified handover payload
  • 400 Missing or invalid shop identifier
  • 401 Unsigned, forged, expired, or cross-shop handover token
  • 500 Handover verification is unavailable
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/handover/verify \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "verifyToken": "example_verifyToken"
}'

Other

POST

Inspect experiment conflicts

/experiments/conflicts

Request body

{
  selectors: string[]
  exclude_experiment_id?: string (uuid)
}

Responses

  • 200 Conflict analysis
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/conflicts \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "selectors": [],
  "exclude_experiment_id": "uuid-here"
}'
PATCH

Update experiment QA

/experiments/{id}/qa

Responses

  • 200 QA updated
  • 400
  • 401
  • 403
  • 404
  • 409
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/experiments/exp_123/qa \
  -H "Authorization: Bearer <apex-secret-key>"
DELETE

Reset experiment QA

/experiments/{id}/qa

Responses

  • 200 QA reset
  • 400
  • 401
  • 403
  • 404
  • 409
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/experiments/exp_123/qa \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Read QA run

/experiments/{id}/qa/run

Responses

  • 200 QA run, including QA destination URLs for goals on pages outside experiment targeting (goal-page entries in urls, and goalPageDestinations evidence on the qa_url_coverage checklist item)
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/experiments/exp_123/qa/run \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update QA run

/experiments/{id}/qa/run

Request body

{
  runId: string
  itemId?: string
  status?: "pending" | "pass" | "warning" | "fail" | "accepted" | "skipped"
  notes?: string
  evidence?: object
  runNotes?: string
  acceptanceCriteriaSummary?: string,null
}

Responses

  • 200 QA run updated
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/experiments/exp_123/qa/run \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "runId": "example_runId"
}'
POST

Add a custom QA checklist item

/experiments/{id}/qa/run

Request body

{
  runId: string
  title: string
  description?: string
  category?: string
  required?: boolean
}

Responses

  • 201 QA checklist item created
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/qa/run \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "runId": "example_runId",
  "title": "example_title"
}'
DELETE

Delete custom QA checklist item

/experiments/{id}/qa/run

Parameters

  • runId in query
  • itemId in query

Request body

{
  runId?: string
  itemId?: string
}

Responses

  • 200 QA run deleted
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/experiments/exp_123/qa/run \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "runId": "example_runId",
  "itemId": "example_itemId"
}'
POST

Retired experiment launch endpoint

/experiments/{id}/start

This endpoint is gone. Launch traffic through the dashboard approval workflow.

Responses

  • 410 Launch is dashboard-only
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/start \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create harness session

/harness/sessions

Request body

{
  experimentId?: string
  variationId?: string
  experimentSlug: string
  experimentName: string
  variationSlug: string
  variationName: string
  targetUrl: string (uri)
  resetJs?: string,null
  antiFlickerSelectors?: string[]
  ttlSeconds?: integer
}

Responses

  • 201 Harness session created
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/harness/sessions \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "experimentSlug": "example_experimentSlug",
  "experimentName": "example_experimentName",
  "variationSlug": "example_variationSlug",
  "variationName": "example_variationName",
  "targetUrl": "https://example.com"
}'
POST

Create harness session version

/harness/sessions/{id}/versions

Responses

  • 201 Version created
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/harness/sessions/exp_123/versions \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List backlog

/backlog

Parameters

  • limit in query
  • cursor in query
  • include_archived in query - Include archived backlog items when true.

Responses

  • 200 Paginated backlog
  • 400
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/backlog \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create a backlog item

/backlog

Request body

{ $ref: "BacklogCreate" }

Responses

  • 201 Created
  • 400
  • 401
  • 403
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/backlog \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
GET

List the shop's idea fields

/backlog/fields

The field definitions whose values ride on each idea's custom_fields.

Parameters

  • include_archived in query - Include archived fields when true.

Responses

  • 200 Field definitions, in sheet order
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/backlog/fields \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Add an idea field

/backlog/fields

Request body

{ $ref: "BacklogFieldCreate" }

Responses

  • 201 Created
  • 400
  • 401
  • 403
  • 409
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/backlog/fields \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
PATCH

Reorder the idea fields

/backlog/fields

Places the live fields. Every named field must be live, and the resulting positions must be unique across the whole live sheet, so send the sheet rather than one row when two fields swap places. The body is the bare array or the same array under an order key.

Request body

unknown

Responses

  • 200 Field definitions, in the new order
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/backlog/fields \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
PATCH

Update an idea field

/backlog/fields/{id}

Request body

{ $ref: "BacklogFieldUpdate" }

Responses

  • 200 Updated
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/backlog/fields/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE

Archive an idea field

/backlog/fields/{id}

Archiving keeps the values already stored on ideas. The field disappears from reads and rejects new writes.

Responses

  • 200 Archived
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/backlog/fields/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Get a backlogitem

/backlog/{id}

Responses

  • 200 Resource
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/backlog/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update a backlogitem

/backlog/{id}

Request body

{ $ref: "BacklogUpdate" }

Responses

  • 200 Updated
  • 400
  • 401
  • 403
  • 404
  • 409 Backlog item changed after it was loaded. Reload the item, take its fresh version, and retry.
  • 422
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/backlog/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE

Archive a backlog item

/backlog/{id}

Archives the backlog item instead of destroying it.

Responses

  • 200 Deleted
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/backlog/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Get an idea's design board

/backlog/{id}/design

Mockups, links, inspiration, and internal build notes, plus every Research Hub mirror the item carries. The internal half (build notes, inspiration, and links whose switch is off) is redacted for a client viewer: a client shop role in the dashboard, and a user API key whose holder holds one. A secret API key is minted with apikeys:manage, which no client role holds, so it reads the whole board.

Responses

  • 200 Design board
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/backlog/exp_123/design \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update an idea's design board

/backlog/{id}/design

Replaces the keys it carries and leaves the rest alone. Arrays replace wholesale.

Request body

{ $ref: "BacklogItemDesignPatch" }

Responses

  • 200 Updated design board
  • 400
  • 401
  • 403
  • 404
  • 409 The idea changed while saving
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/backlog/exp_123/design \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
POST

Archive a backlog item and reject its roadmap decision

/backlog/{id}/archive

Request body

{
  feedback?: string,null
  reason?: string,null
}

Responses

  • 200 Archived backlog item
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/backlog/exp_123/archive \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
POST

Approve a backlog idea into a month

/backlog/{id}/approve

Schedules the idea and records who decided. On a shop where DRIP decides the backlog, a client principal is refused with 403.

Request body

{
  roadmap_month: string
  comment?: string,null
}

Responses

  • 200 The idea's decision after approving
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/backlog/exp_123/approve \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "roadmap_month": "example_roadmap_month"
}'
POST

Reject a backlog idea with a reason

/backlog/{id}/reject

Records the rejection and its reason. The idea stays in the backlog, shown as rejected, rather than being archived.

Request body

{
  reason_category: "not_right_for_brand" | "already_tested" | "too_much_effort" | "other"
  reason: string
}

Responses

  • 200 The idea's decision after rejecting
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/backlog/exp_123/reject \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "reason_category": "not_right_for_brand",
  "reason": "example_reason"
}'
POST

Restore an archived backlog item and reset its roadmap decision to proposed

/backlog/{id}/restore

Responses

  • 200 Restored backlog item
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/backlog/exp_123/restore \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List personalizations

/personalizations

Parameters

  • limit in query
  • cursor in query

Responses

  • 200 Personalizations with cursor pagination
  • 400
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/personalizations \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create personalization

/personalizations

Request body

{ $ref: "PersonalizationInput" }

Responses

  • 201 Created personalization
  • 400
  • 401
  • 403
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/personalizations \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
GET

Get personalization

/personalizations/{id}

Responses

  • 200 Personalization
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/personalizations/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update personalization

/personalizations/{id}

Request body

{ $ref: "PersonalizationUpdateInput" }

Responses

  • 200 Updated personalization
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/personalizations/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
POST

Activate personalization

/personalizations/{id}/activate

Responses

  • 200 Updated personalization
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/personalizations/exp_123/activate \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Pause personalization

/personalizations/{id}/pause

Responses

  • 200 Updated personalization
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/personalizations/exp_123/pause \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Archive personalization

/personalizations/{id}/archive

Responses

  • 200 Updated personalization
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/personalizations/exp_123/archive \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List assets

/assets

Parameters

  • include_archived in query - Include archived assets.
  • limit in query
  • cursor in query

Responses

  • 200 Assets with cursor pagination
  • 400
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/assets \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Upload assets

/assets

Responses

  • 201 Uploaded assets
  • 400
  • 401
  • 403
  • 413 Too many files or a file exceeds the upload size limit.
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/assets \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Get asset

/assets/{id}

Parameters

  • id in path required

Responses

  • 200 Asset
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/assets/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
DELETE

Archive asset

/assets/{id}

Archives the asset without deleting its stored file; it can be restored.

Parameters

  • id in path required

Responses

  • 200 Deleted
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/assets/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Restore asset

/assets/{id}/restore

Parameters

  • id in path required

Responses

  • 200 Restored asset
  • 404
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/assets/exp_123/restore \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Read data-deletion status

/data-deletion

Parameters

  • request_id in query
  • visitor_id in query

Responses

  • 200 Deletion status
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/data-deletion \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Request data deletion

/data-deletion

Request body

{
  visitor_id: string
}

Responses

  • 202 Deletion accepted
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/data-deletion \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "visitor_id": "example_visitor_id"
}'
GET

Export personal data

/data-export

Parameters

  • request_id in query
  • visitor_id in query

Responses

  • 200 Data export
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/data-export \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Request a personal data export

/data-export

Request body

{
  limit?: integer
  visitor_id: string
}

Responses

  • 200 Completed data export
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/data-export \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "limit": 1,
  "visitor_id": "example_visitor_id"
}'
GET

List exclusion groups

/exclusion-groups

Parameters

  • limit in query
  • cursor in query
  • include_archived in query - Include archived exclusion groups.

Responses

  • 200 exclusion groups list
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/exclusion-groups \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create exclusion groups

/exclusion-groups

Request body

{ $ref: "ExclusionGroupInput" }

Responses

  • 201 exclusion groups created
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/exclusion-groups \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
GET

Get exclusion group

/exclusion-groups/{id}

Parameters

  • id in path required

Responses

  • 200 exclusion group returned
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/exclusion-groups/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update exclusion group

/exclusion-groups/{id}

Parameters

  • id in path required

Request body

{ $ref: "ExclusionGroupUpdateInput" }

Responses

  • 200 exclusion group returned
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/exclusion-groups/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE

Archive exclusion group

/exclusion-groups/{id}

Archives the group while preserving membership.

Parameters

  • id in path required

Responses

  • 200 exclusion group deleted
  • 400
  • 401
  • 403
  • 404
  • 409
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/exclusion-groups/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PUT

Replace exclusion group members

/exclusion-groups/{id}/members

Parameters

  • id in path required

Request body

{ $ref: "ExclusionGroupMembersInput" }

Responses

  • 200 Exclusion group members replaced
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X PUT \
  https://app.drip-apex.com/api/v1/exclusion-groups/exp_123/members \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
POST

Restore exclusion group

/exclusion-groups/{id}/restore

Parameters

  • id in path required

Responses

  • 200 Exclusion group restored
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/exclusion-groups/exp_123/restore \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Generate external purchase pixel snippet

/external-pixels/snippet

Requires a secret API key with the external_pixels:write scope; the response embeds a signed ingest credential, so read-scoped and publishable keys receive 403 Forbidden.

Request body

{
  globalName?: string
  handoverParam?: string
  provider?: string
}

Responses

  • 200 Generated snippet
  • 400
  • 401
  • 403
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/external-pixels/snippet \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "globalName": "example_globalName",
  "handoverParam": "example_handoverParam",
  "provider": "example_provider"
}'
GET

List flags

/flags

Parameters

  • limit in query
  • cursor in query

Responses

  • 200 Flags with cursor pagination
  • 400
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/flags \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create flag

/flags

Request body

{ $ref: "FeatureFlagInput" }

Responses

  • 201 Created flag
  • 400
  • 401
  • 403
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/flags \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
GET

Get flag

/flags/{id}

Parameters

  • id in path required

Responses

  • 200 Flag
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/flags/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update flag

/flags/{id}

Parameters

  • id in path required

Request body

{ $ref: "FeatureFlagUpdateInput" }

Responses

  • 200 Updated flag
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/flags/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
POST

Activate flag

/flags/{id}/activate

Parameters

  • id in path required

Responses

  • 200 Updated flag
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/flags/exp_123/activate \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Archive flag

/flags/{id}/archive

Parameters

  • id in path required

Responses

  • 200 Updated flag
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/flags/exp_123/archive \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Pause flag

/flags/{id}/pause

Parameters

  • id in path required

Responses

  • 200 Updated flag
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/flags/exp_123/pause \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Get flag edge publication status

/flags/{id}/status

Returns database publication metadata, the propagation worst-case window derived from the shop's effective runtime cache TTLs, and, for visual flags, the public edge config URL used to confirm propagation. Edge propagation does not apply to API-delivered flags.

Parameters

  • id in path required

Responses

  • 200 Flag publication status
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/flags/exp_123/status \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List funnels

/funnels

Parameters

  • limit in query
  • cursor in query
  • include_archived in query - Include archived funnels.

Responses

  • 200 funnels list
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/funnels \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create funnels

/funnels

Request body

{ $ref: "FunnelInput" }

Responses

  • 201 funnels created
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/funnels \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
GET

Get funnel

/funnels/{id}

Parameters

  • id in path required

Responses

  • 200 funnel returned
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/funnels/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update funnel

/funnels/{id}

Parameters

  • id in path required

Request body

{ $ref: "FunnelUpdateInput" }

Responses

  • 200 funnel returned
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/funnels/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE

Archive funnel

/funnels/{id}

Archives the funnel instead of destroying it.

Parameters

  • id in path required

Responses

  • 200 funnel deleted
  • 400
  • 401
  • 403
  • 404
  • 409
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/funnels/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Restore funnel

/funnels/{id}/restore

Parameters

  • id in path required

Responses

  • 200 Restored funnel
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/funnels/exp_123/restore \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List landing pages

/landing-pages

Requires the Apex Labs feature for the shop; shops without it receive 404 Not Found.

Parameters

  • limit in query
  • cursor in query
  • status in query

Responses

  • 200 Landing pages with cursor pagination
  • 400
  • 401
  • 403
  • 404 Apex Labs is not enabled for this shop, so landing pages are unavailable.
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/landing-pages \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Get landing page

/landing-pages/{id}

Parameters

  • id in path required

Responses

  • 200 Landing page
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/landing-pages/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List pages

/pages

Parameters

  • limit in query
  • cursor in query

Responses

  • 200 pages list
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/pages \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create pages

/pages

Request body

{ $ref: "PageInput" }

Responses

  • 201 pages created
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/pages \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
GET

Get page

/pages/{id}

Parameters

  • id in path required

Responses

  • 200 page returned
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/pages/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update page

/pages/{id}

Parameters

  • id in path required

Request body

{ $ref: "PageUpdateInput" }

Responses

  • 200 page returned
  • 400
  • 401
  • 403
  • 404
  • 409 Conflict. A live-consumer acknowledgement conflict returns the PageLiveImpactError shape — repeat the request with confirm_live_impact and confirmed_consumer_ids carrying every id listed. A trigger-propagation race or duplicate API name returns the generic Error shape.
  • 422
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/pages/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE

Delete page

/pages/{id}

Parameters

  • id in path required

Responses

  • 200 page deleted
  • 400
  • 401
  • 403
  • 404
  • 409
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/pages/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List segments

/segments

Parameters

  • limit in query
  • cursor in query

Responses

  • 200 segments list
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/segments \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create segments

/segments

Request body

{ $ref: "SegmentInput" }

Responses

  • 201 segments created
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/segments \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
PATCH

Update segment

/segments/{id}

Parameters

  • id in path required

Request body

{ $ref: "SegmentUpdateInput" }

Responses

  • 200 segment returned
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/segments/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE

Delete segment

/segments/{id}

Parameters

  • id in path required

Responses

  • 200 segment deleted
  • 400
  • 401
  • 403
  • 404
  • 409
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/segments/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List signals

/signals

The first page includes the built-in signal catalog before paginated custom signals. Built-ins do not participate in cursor pagination.

Parameters

  • limit in query
  • cursor in query
  • include_archived in query - Include archived custom signals when true. Built-in signals are always active.

Responses

  • 200 Paginated signals
  • 400
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/signals \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create a signal

/signals

Request body

{ $ref: "SignalCreate" }

Responses

  • 201 Created
  • 400
  • 401
  • 403
  • 409
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/signals \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
GET

Get a signal

/signals/{id}

Parameters

  • id in path required - Custom signal UUID or built-in catalog signal key (e.g. url.full).

Responses

  • 200 Resource
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/signals/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update a signal

/signals/{id}

Parameters

  • id in path required - Custom signal UUID or built-in catalog signal key (e.g. url.full).

Request body

{ $ref: "SignalUpdate" }

Responses

  • 200 Updated
  • 400
  • 401
  • 403
  • 404
  • 409
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/signals/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE

Delete or archive a signal

/signals/{id}

Parameters

  • id in path required - Custom signal UUID or built-in catalog signal key (e.g. url.full).

Responses

  • 200 Deleted or archived
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/signals/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"

Experiments

POST

Attach or upload QA evidence

/experiments/{id}/qa/evidence

Attaches a terminal screenshot job, writes typed evidence records, or uploads QA evidence images. Exactly one request form is accepted per call.

Request body

unknown

Responses

  • 200 Signed QA run with the updated evidence
  • 400
  • 401
  • 403
  • 404
  • 409
  • 429
  • 502 Evidence upload failed
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/qa/evidence \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
POST

Create an artifact-injecting proxy preview session

/preview-sessions

Requires a secret API key with experiments:write. The returned short-lived URL is a bearer capability that renders the selected draft variation without a dashboard session or installed Apex snippet.

Request body

{
  experiment_id: string
  variation_id?: string
  target_url?: string (uri)
  ttl_hours?: integer = 168
}

Responses

  • 200 Preview session
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/preview-sessions \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "experiment_id": "example_experiment_id",
  "variation_id": "example_variation_id",
  "target_url": "https://example.com",
  "ttl_hours": 168
}'
GET

List experiments

/experiments

Returns a paginated list of experiments. Supports cursor-based pagination and optional status filter.

Parameters

  • status in query
  • archived in query - Set to 1 to include archived experiments
  • limit in query
  • cursor in query - ID of the last item from the previous page

Responses

  • 200 Paginated list of experiments
  • 401 Unauthorized
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/experiments \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create experiment

/experiments

Creates a new experiment. Default control and variant are created if variations are not provided. Omitted statistical settings use the shop testing defaults. Experiments authenticated with a user API key default owner_user_id to that key's user; organization- and shop-scoped keys have no user and leave the owner null.

Request body

{
  name: string
  slug?: string | null
  description?: string | null
  backlog_item_id?: string (uuid)
  idea_key?: string
  as_follow_up?: boolean = false
  owner_user_id?: string,null (uuid)
  counting_type?: "standard" | "setup_test" | "aa_test" | "non_program"
  delivery_type?: "mutation" | "redirect"
  type?: "standard" | "setup_test" | "aa_test" | "non_program"
  experiment_type?: "mutation" | "redirect"
  traffic_allocation?: number = 1
  experiment_js?: string | null
  experiment_reset_js?: string | null
  experiment_css?: string | null
  sequential_testing_enabled?: boolean
  significance_level?: number
  statistical_power?: number
  store_url?: string (uri)
  auto_stop_override?: AutoStopOverride
  guardian_override?: GuardianOverride
  targeting?: any
  variations?: object[]
  primary_goal_id?: string (uuid)
  goal_ids?: string[]
}

Responses

  • 200 Existing experiment already linked to the backlog item
  • 201 Experiment created
  • 400 Validation error
  • 401 Unauthorized
  • 404 Backlog item not found for this shop
  • 422 Backlog item requires customer approval or the dashboard landing-page handoff, or both backlog_item_id and idea_key were sent
  • 429 Rate limit exceeded
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "example_name"
}'
GET

Get experiment

/experiments/{id}

Returns a single experiment by ID with variations and goals.

Parameters

  • id in path required

Responses

  • 200 Experiment details
  • 404 Experiment not found
cURL
curl \
  https://app.drip-apex.com/api/v1/experiments/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update experiment

/experiments/{id}

Partially updates an experiment. Cannot update completed experiments.

Parameters

  • id in path required

Request body

{
  name?: string
  slug?: string | null
  description?: string | null
  owner_user_id?: string,null (uuid)
  counting_type?: "standard" | "setup_test" | "aa_test" | "non_program"
  type?: "standard" | "setup_test" | "aa_test" | "non_program"
  traffic_allocation?: number
  experiment_js?: string | null
  experiment_reset_js?: string | null
  experiment_css?: string | null
  sequential_testing_enabled?: boolean
  store_url?: string (uri)
  auto_stop_override?: AutoStopOverride
  guardian_override?: GuardianOverride
  targeting?: any
  confirmTargetingReplace?: boolean
}

Responses

  • 200 Experiment updated
  • 400 Cannot update completed experiment
  • 404 Experiment not found
  • 409 Targeting replacement requires confirmation (error.code confirm_targeting_replace_required): the update would replace the experiment's author-explicit URL targeting with a page-entity rule. Retry with confirmTargetingReplace: true.
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/experiments/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE

Archive experiment

/experiments/{id}

Archives an experiment while preserving its variations and results history.

Parameters

  • id in path required

Responses

  • 200 Experiment deleted
  • 404 Experiment not found
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/experiments/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Read experiment filesystem

/experiments/{id}/filesystem

Returns the complete canonical filesystem snapshot for an experiment. File hashes can be used to detect changes before planning a write.

Parameters

  • id in path required

Responses

  • 200 Canonical experiment filesystem
  • 401 Unauthorized
  • 404 Experiment not found
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/experiments/exp_123/filesystem \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Plan an experiment filesystem apply

/experiments/{id}/filesystem/plan

Validates a complete filesystem snapshot and reports the changes without writing them. Draft experiments accept all supported filesystem changes. Paused experiments accept treatment-content changes and redirect destinations. Running experiments accept treatment-content changes only; redirect destinations remain draft/paused-only. Structural changes remain draft-only and are reported with the offending file paths.

Parameters

  • id in path required

Request body

{
  files: object[]
}

Responses

  • 200 Filesystem apply plan
  • 400 Invalid request body
  • 401 Unauthorized
  • 404 Experiment not found
  • 429 Rate limit exceeded
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/filesystem/plan \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "files": []
}'
POST

Apply an experiment filesystem

/experiments/{id}/filesystem/apply

Atomically applies experiment, goal, variation, and variation-artifact changes to draft experiments. Paused experiments accept treatment-content changes and redirect destinations. Running experiments accept treatment-content changes only; redirect destinations remain draft/paused-only. Structural changes remain draft-only and fail closed with the offending file paths. Running artifact writes republish the storefront configuration. A successful response with applied=true means every database change committed. applied=false means no changes from this request committed, except when saved=true reports a committed artifact whose storefront publication failed. Identically re-applying an already committed snapshot is safe and converges on the same final state.

Parameters

  • id in path required

Request body

{
  files: object[]
}

Responses

  • 200 Atomic apply outcome
  • 400 Invalid request body
  • 401 Unauthorized
  • 404 Experiment not found
  • 429 Rate limit exceeded
  • 500 Unexpected failure; the atomic database transaction was rolled back and no filesystem changes committed.
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/filesystem/apply \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "files": []
}'
GET

Get experiment results

/experiments/{id}/results

Returns the canonical experiment results read model, including totals, arms, decision, metrics, timeseries, warnings, and delivery health.

Parameters

  • id in path required
  • currency in query - Optional ISO currency code for revenue diagnostics.

Responses

  • 200 Experiment results
  • 401 Unauthorized
  • 403 API key is missing experiment read permission
  • 404 Experiment not found
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/experiments/exp_123/results \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Get experiment by slug

/experiments/by-slug/{slug}

Fetch a single experiment by slug (scoped to the API key's shop).

Parameters

  • slug in path required

Responses

  • 200 Experiment details
  • 401 Unauthorized
  • 404 Experiment not found
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/experiments/by-slug/example_slug \
  -H "Authorization: Bearer <apex-secret-key>"
PUT

Upsert experiment by slug

/experiments/by-slug/{slug}

Idempotently create or update a draft experiment by slug. New experiments use the shop testing defaults for omitted statistical settings and default owner_user_id to the authenticated user for user API keys; organization- and shop-scoped keys leave the owner null. If an experiment exists with this slug and is not in draft status, returns 409.

Parameters

  • slug in path required

Request body

{
  name: string
  description?: string | null
  counting_type?: "standard" | "setup_test" | "aa_test" | "non_program"
  delivery_type?: "mutation" | "redirect"
  type?: "standard" | "setup_test" | "aa_test" | "non_program"
  experiment_type?: "mutation" | "redirect"
  traffic_allocation?: number = 1
  experiment_js?: string | null
  experiment_reset_js?: string | null
  experiment_css?: string | null
  sequential_testing_enabled?: boolean
  significance_level?: number
  statistical_power?: number
  store_url?: string (uri)
  auto_stop_override?: AutoStopOverride
  targeting?: any
  variations: object[]
  primary_goal_id?: string (uuid)
  goal_ids?: string[]
}

Responses

  • 200 Experiment updated
  • 201 Experiment created
  • 400 Validation error
  • 401 Unauthorized
  • 409 Conflict (experiment not in draft status or slug already exists)
  • 429 Rate limit exceeded
  • 503
cURL
curl -X PUT \
  https://app.drip-apex.com/api/v1/experiments/by-slug/example_slug \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "example_name",
  "variations": []
}'
POST

Attach an idea to an experiment

/experiments/{id}/idea

Links the experiment to one idea. Send exactly one of backlog_item_id or idea_key. Repeating the request returns the existing link with 200 and writes no audit entry.

Parameters

  • id in path required

Request body

{
  backlog_item_id?: string (uuid)
  idea_key?: string
  as_follow_up?: boolean = false
}

Responses

  • 200 The experiment was already linked to this idea
  • 201 Idea attached
  • 400 No identifier, or a field of the wrong type
  • 404 Experiment or idea not found
  • 409 Experiment or idea already has a primary link
  • 422 Both backlog_item_id and idea_key were sent
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/idea \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "backlog_item_id": "uuid-here",
  "idea_key": "example_idea_key",
  "as_follow_up": false
}'
DELETE

Detach the linked idea from an experiment

/experiments/{id}/idea

Removes one idea link. Without an identifier the primary link goes first, then the oldest link.

Parameters

  • id in path required
  • backlog_item_id in query - Remove the link to this idea instead of the primary link.
  • idea_key in query - Shop backlog key alternative to backlog_item_id.

Responses

  • 200 Idea detached
  • 404 Experiment or idea link not found
  • 422 Both backlog_item_id and idea_key were sent
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/experiments/exp_123/idea \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Pause experiment

/experiments/{id}/pause

Pauses a running experiment.

Parameters

  • id in path required

Responses

  • 200 Experiment paused
  • 400 Only running experiments can be paused
  • 404 Experiment not found
  • 502 Commerce configuration failed before commit, or the lifecycle change committed but storefront publication failed
  • 503 Publication lock contended; retry after the Retry-After interval
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/pause \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Complete experiment

/experiments/{id}/complete

Marks a running or paused experiment as completed. Sets ended_at timestamp.

Parameters

  • id in path required

Responses

  • 200 Experiment completed
  • 400 Only running or paused experiments can be completed
  • 404 Experiment not found
  • 502 Commerce configuration failed before commit, or the lifecycle change committed but storefront publication failed
  • 503 Publication lock contended; retry after the Retry-After interval
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/complete \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Duplicate experiment

/experiments/{id}/duplicate

Creates a faithful copy of the experiment in draft status with its configuration, variation artifacts, landing-page bindings, and goal associations. Review, scheduling, runtime, and result state do not carry over.

Parameters

  • id in path required

Responses

  • 201 Duplicate experiment created
  • 400 A variation artifact could not be copied; no duplicate is created
  • 404 Experiment not found
  • 409 A concurrent write caused a temporary transaction conflict (error code tx_write_conflict); retry the request.
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/duplicate \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Generate experiment with AI

/experiments/generate

Uses AI to generate an experiment configuration based on a store URL and prompt.

Request body

{
  store_url: string (uri)
  prompt: string
  primary_goal_id?: string (uuid)
  goal_ids?: string[]
  traffic_allocation?: number = 1
  targeting?: any
  screenshot_devices?: string[]
}

Responses

  • 201 AI-generated experiment created
  • 400 Validation error
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/generate \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "store_url": "https://example.com",
  "prompt": "example_prompt"
}'

Platform admin

GET

Read allowlisted platform settings

/admin/settings

Requires an admin:read user API key and a live PlatformAccess row; environment email grants do not apply.

Responses

  • 200 Settings
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/admin/settings \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update allowlisted platform settings

/admin/settings

Only guardian_enabled and srm_check_enabled are accepted.

Request body

{
  guardian_enabled?: boolean
  srm_check_enabled?: boolean
}

Responses

  • 200 Settings updated
  • 400
  • 401
  • 403
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/admin/settings \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "guardian_enabled": false,
  "srm_check_enabled": false
}'
POST

Archive a shop

/admin/shops/{id}/archive

Requires an admin:write user API key and refuses shops with running, non-archived experiments.

Responses

  • 200 Shop archived and delivery disabled
  • 401
  • 403
  • 404 Shop not found (pass-through orchestration body)
  • 409 Shop has running, non-archived experiments
  • 429
  • 503 Archival persisted but snippet republication pending, or publication lock contention — retriable
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/admin/shops/exp_123/archive \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Restore an archived shop

/admin/shops/{id}/restore

Requires an admin:write user API key. Delivery remains controlled by the shop runtime kill switch.

Responses

  • 200 Shop restored
  • 401
  • 403
  • 404 Shop not found (pass-through orchestration body)
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/admin/shops/exp_123/restore \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List tracking quarantine events

/admin/tracking/quarantine

Read-only platform view requiring a live PlatformAccess row.

Parameters

  • shopId in query
  • reasonCode in query
  • verdict in query
  • limit in query

Responses

  • 200 Quarantine rows
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/admin/tracking/quarantine \
  -H "Authorization: Bearer <apex-secret-key>"

Account

GET

Get the current user's profile

/account/profile

Responses

  • 200 Account profile
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/account/profile \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update the current user's profile

/account/profile

Request body

{
  displayName?: string
  avatarDataUrl?: string,null
}

Responses

  • 200 Updated account profile
  • 400
  • 401
  • 403
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/account/profile \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "displayName": "example_displayName"
}'

API keys

GET

List a shop's API keys

/keys

Parameters

  • shop_id in query required

Responses

  • 200 API key metadata; hashes and secrets are never included
  • 400
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/keys \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create a shop API key

/keys

Request body

{
  shop_id: string (uuid)
  name: string
  type: "live_secret" | "test_secret" | "publishable"
  permissions?: string[]
  rate_limit?: integer
  expires_at?: string,null (date-time)
}

Responses

  • 201 Created key, including its secret exactly once
  • 400
  • 403
  • 404
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/keys \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "shop_id": "uuid-here",
  "name": "example_name",
  "type": "live_secret"
}'
DELETE

Revoke a shop API key

/keys/{id}

Parameters

  • id in path required
  • shop_id in query required

Responses

  • 200 Revoked
  • 400
  • 403
  • 404
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/keys/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"

External tracking

GET

Read cross-domain identity handover settings

/external-tracking

Responses

  • 200 External tracking settings
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/external-tracking \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update cross-domain identity handover settings

/external-tracking

Request body

{
  externalTracking?: object
  ifRevision?: string,null (date-time)
}

Responses

  • 200 Updated handover settings and edge precompile outcome
  • 400
  • 401
  • 403
  • 409
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/external-tracking \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "externalTracking": {}
}'

Variations

POST

Generate variation with AI

/experiments/{id}/variations/generate

Uses AI to generate a new variation for an existing experiment.

Parameters

  • id in path required - Experiment ID

Request body

{
  prompt: string
}

Responses

  • 201 AI-generated variation created
  • 400 Validation error
  • 404 Experiment not found
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/variations/generate \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "example_prompt"
}'
POST

Create variation

/variations

Creates a new variation for a draft experiment. Requires experiment_id in the body.

Request body

{
  experiment_id: any
  name: string
  weight: number
  is_control?: boolean = false
  redirect_url?: string (uri)
  mutations?: Mutation[]
  url_blocks?: UrlBlocks
  custom_css?: string | null
  custom_js?: string | null
}

Responses

  • 201 Variation created
  • 400 Validation error or experiment not in draft status
  • 404 Experiment not found
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/variations \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "example_name",
  "weight": 1
}'
GET

Get variation

/variations/{id}

Returns a single variation by ID.

Parameters

  • id in path required

Responses

  • 200 Variation details
  • 403 Not authorized to access this variation
  • 404 Variation not found
cURL
curl \
  https://app.drip-apex.com/api/v1/variations/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update variation

/variations/{id}

Partially updates a variation. Treatment artifacts (mutations, URL blocks, and custom CSS/JavaScript) can change while the experiment is draft, paused, or running. Running artifact writes republish the storefront configuration. Other variation fields remain draft-only. Cannot update is_control.

Parameters

  • id in path required

Request body

{
  name?: string
  weight?: number
  redirect_url?: string (uri)
  expected_prior_redirect_url?: string (uri)
  mutations?: Mutation[]
  url_blocks?: UrlBlocks
  custom_css?: string | null
  custom_js?: string | null
}

Responses

  • 200 Variation updated
  • 400 The write was rejected, or treatment artifacts committed before a later publication step reported a failure
  • 403 Not authorized
  • 404 Variation not found
  • 409 Treatment artifacts cannot change after the experiment finishes, the redirect destination changed since it was read, the experiment is no longer editable, or a price-test mutation targets a subscription-priced or bundle-component variant
  • 502 The running treatment artifact was saved, but storefront publication failed
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/variations/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE

Archive variation

/variations/{id}

Archives a non-control variation from a draft experiment. Minimum 2 active variations must remain, and remaining active weights are redistributed.

Parameters

  • id in path required

Responses

  • 200 Variation archived
  • 400 Cannot delete control, non-draft experiment, or last two variations
  • 403 Not authorized
  • 404 Variation not found
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/variations/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Restore variation

/variations/{id}/restore

Restores an archived variation and redistributes all active variation weights.

Parameters

  • id in path required

Responses

  • 200 Variation restored
  • 404 Variation not found
  • 409 Variation is already active or changed concurrently
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/variations/exp_123/restore \
  -H "Authorization: Bearer <apex-secret-key>"

Apex Workspace

GET

Read variation workspace

/experiments/{id}/variations/{variationId}/workspace

Returns the canonical Apex workspace for an exact experiment variation. Used by `apex workspace checkout`.

Parameters

  • id in path required - Experiment ID
  • variationId in path required - Variation ID

Responses

  • 200 Canonical workspace payload
  • 401 Unauthorized
  • 403 Not authorized to access this variation
  • 404 Experiment variation workspace not found
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/experiments/exp_123/variations/variation_123/workspace \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List variation workspace files

/experiments/{id}/variations/{variationId}/files

Lists canonical workspace files for an exact experiment variation.

Parameters

  • id in path required
  • variationId in path required

Responses

  • 200 Workspace files
  • 401 Unauthorized
  • 403 Not authorized to access this variation
  • 404 Experiment variation workspace not found
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/experiments/exp_123/variations/variation_123/files \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Read variation workspace file

/experiments/{id}/variations/{variationId}/files/{path}

Reads one canonical workspace file. URL-encode the file path, for example src%2Findex.js.

Parameters

  • id in path required
  • variationId in path required
  • path in path required - Canonical workspace path, URL-encoded. Supported roots: src, goals, segments, network, metrics.json, targeting.json, experiment.config.json, dev-doc.md.

Responses

  • 200 Workspace file
  • 401 Unauthorized
  • 403 Not authorized to access this variation
  • 404 Workspace file not found
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/experiments/exp_123/variations/variation_123/files/example_path \
  -H "Authorization: Bearer <apex-secret-key>"
PUT

Write variation workspace file

/experiments/{id}/variations/{variationId}/files/{path}

Writes one canonical workspace file and records a workspace revision. Supply expected_version from the current file sha256 to reject a concurrent edit.

Parameters

  • id in path required
  • variationId in path required
  • path in path required - Canonical workspace path, URL-encoded. Supported roots: src, goals, segments, network, metrics.json, targeting.json, experiment.config.json, dev-doc.md.

Request body

{
  content: string
  source?: "manual" | "operator" | "build" | "system"
  title?: string
  expected_version?: string
}

Responses

  • 200 Workspace file write result
  • 400 Validation error or unsupported workspace path
  • 401 Unauthorized
  • 403 Not authorized to edit this variation
  • 404 Experiment variation workspace not found
  • 409 The workspace file changed or no longer exists
  • 429 Rate limit exceeded
  • 503
cURL
curl -X PUT \
  https://app.drip-apex.com/api/v1/experiments/exp_123/variations/variation_123/files/example_path \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "content": "example_content",
  "source": "manual",
  "title": "example_title",
  "expected_version": "example_expected_version"
}'
POST

Build variation workspace

/experiments/{id}/variations/{variationId}/build

Projects canonical workspace files into Apex runtime state: mutations, CSS, JS, targeting, goals, and segments.

Parameters

  • id in path required
  • variationId in path required

Request body

{
  mode?: "full" | "validate_only"
  allowGoalWrites?: boolean = false
}

Responses

  • 200 Workspace build succeeded
  • 400 Workspace build failed
  • 401 Unauthorized
  • 403 Not authorized to edit this variation
  • 404 Experiment variation workspace not found
  • 409 Workspace build conflicted with a concurrent artifact save
  • 429 Rate limit exceeded
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/variations/variation_123/build \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "mode": "full",
  "allowGoalWrites": false
}'
GET

List variation workspace revisions

/experiments/{id}/variations/{variationId}/revisions

Lists recent workspace revisions for an exact experiment variation.

Parameters

  • id in path required
  • variationId in path required

Responses

  • 200 Workspace revisions
  • 401 Unauthorized
  • 403 Not authorized to access this variation
  • 404 Experiment variation workspace not found
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/experiments/exp_123/variations/variation_123/revisions \
  -H "Authorization: Bearer <apex-secret-key>"

Targeting

GET

Test URL targeting

/targeting/test

Evaluates the API key shop's experiment targeting rules against one URL and returns all matching experiments for parallel-experiment awareness.

Parameters

  • url in query required
  • status in query - Comma-separated statuses or all. Defaults to draft,qa,running,paused.

Responses

  • 200 Targeting evaluation
  • 400 Invalid URL
  • 401 Unauthorized
  • 403 API key is missing experiment read permission
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/targeting/test \
  -H "Authorization: Bearer <apex-secret-key>"

Harness

POST

Publish harness session

/harness/sessions/{id}/publish

Publishes reviewed harness artifacts to the session variation.

Parameters

  • id in path required

Responses

  • 200 Harness session published
  • 400 Artifact review blocked publish
  • 404 Harness session not found
  • 409 Experiment is not in draft status
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/harness/sessions/exp_123/publish \
  -H "Authorization: Bearer <apex-secret-key>"

Screenshots

POST

Create screenshot job

/experiments/{id}/screenshots

Queues a screenshot capture job for the specified variations and devices.

Parameters

  • id in path required - Experiment ID

Request body

{
  devices: string[]
  variation_ids: array
}

Responses

  • 202 Screenshot job queued
  • 400 Validation error
  • 404 Experiment not found
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/experiments/exp_123/screenshots \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "devices": [],
  "variation_ids": []
}'
GET

Get screenshot job status

/screenshots/{jobId}

Returns the current status and results of a screenshot job.

Parameters

  • jobId in path required

Responses

  • 200 Screenshot job details
  • 404 Job not found
cURL
curl \
  https://app.drip-apex.com/api/v1/screenshots/job_123 \
  -H "Authorization: Bearer <apex-secret-key>"

Webhooks

GET

List webhooks

/webhooks

Returns all webhooks for the shop.

Parameters

  • include_archived in query - Include archived webhooks.

Responses

  • 200 List of webhooks
  • 401 Unauthorized
cURL
curl \
  https://app.drip-apex.com/api/v1/webhooks \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create webhook

/webhooks

Registers a new webhook endpoint. URL must use HTTPS. Events: experiment.started, experiment.completed, experiment.significant, experiment.guardian_triggered, experiment.guardian_paused, variation.winning, screenshots.completed, project.published.

Request body

{
  url: string (uri)
  events: string[]
}

Responses

  • 201 Webhook created
  • 400 Validation error
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/webhooks \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com",
  "events": []
}'
GET

Get webhook

/webhooks/{id}

Parameters

  • id in path required

Responses

  • 200 Webhook
  • 404 Webhook not found
cURL
curl \
  https://app.drip-apex.com/api/v1/webhooks/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update webhook

/webhooks/{id}

Parameters

  • id in path required

Request body

{
  url?: string (uri)
  events?: string[]
  active?: boolean
}

Responses

  • 200 Webhook
  • 404 Webhook not found
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/webhooks/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com",
  "events": [],
  "active": false
}'
DELETE

Archive webhook

/webhooks/{id}

Archives a webhook registration while retaining delivery history.

Parameters

  • id in path required

Responses

  • 200 Webhook deleted
  • 404 Webhook not found
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/webhooks/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Restore webhook

/webhooks/{id}/restore

Parameters

  • id in path required

Responses

  • 200 Restored webhook
  • 404 Webhook not found
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/webhooks/exp_123/restore \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List webhook deliveries

/webhooks/{id}/deliveries

Returns recent delivery attempts for one webhook. Delivery IDs are also sent as the X-Apex-Delivery-Id header on outbound webhook requests.

Parameters

  • id in path required
  • status in query
  • limit in query

Responses

  • 200 List of webhook delivery attempts
  • 404 Webhook not found
cURL
curl \
  https://app.drip-apex.com/api/v1/webhooks/exp_123/deliveries \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Send test webhook

/webhooks/{id}/test

Sends a signed test event and records the delivery.

Parameters

  • id in path required

Responses

  • 200 Test delivery
  • 404 Webhook not found
  • 409 Webhook is inactive
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/webhooks/exp_123/test \
  -H "Authorization: Bearer <apex-secret-key>"

Organization

GET

Get the credential organization

/org

Responses

  • 200 Dashboard organization detail shape, including a `members` array (id, userId, email, role, defaultShopRole, createdAt) and `_count.members`.
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/org \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update organization settings

/org

Request body

{
  name?: string
  slug?: string
  billing_email?: string,null
  logo_url?: string,null
  sso_enabled?: boolean
  sso_enforced?: boolean
  sso_domain?: string,null
  sso_provider_id?: string,null
}

Responses

  • 200 Updated organization
  • 401
  • 403
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/org \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
GET

List organization members

/org/members

Responses

  • 200 Members from the dashboard member source
  • 401
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/org/members \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List organization invitations

/org/invitations

Responses

  • 200 Pending invitations
  • 401
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/org/invitations \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Invite an organization member

/org/invitations

Request body

{
  email: string (email)
  org_role?: "admin" | "member"
  default_shop_role?: "editor"
}

Responses

  • 201 Invitation created
  • 401
  • 429
  • 502 The invitation email could not be delivered. The response message says whether the pending invitation was rolled back (safe to retry now) or is still present and blocking retries until it expires
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/org/invitations \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "example_email",
  "org_role": "admin",
  "default_shop_role": "editor"
}'
DELETE

Revoke an organization invitation

/org/invitations/{id}

Parameters

  • id in path required

Responses

  • 200 Invitation revoked
  • 401
  • 404
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/org/invitations/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update an organization member

/org/members/{id}

Parameters

  • id in path required

Request body

{
  role?: string
  default_shop_role?: "editor"
}

Responses

  • 200 Member updated
  • 401
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/org/members/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "role": "example_role",
  "default_shop_role": "editor"
}'
DELETE

Remove an organization member

/org/members/{id}

Parameters

  • id in path required

Responses

  • 200 Member removed
  • 401
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/org/members/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"

Team

GET

List shop team members

/team/members

Parameters

  • shop_id in query required

Responses

  • 200 Team members
  • 401
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/team/members \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List shop invitations

/team/invitations

Parameters

  • shop_id in query required

Responses

  • 200 Invitations
  • 401
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/team/invitations \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Invite a shop member

/team/invitations

Request body

{
  email: string (email)
  role: "editor" | "client_viewer"
  shop_id: string (uuid)
}

Responses

  • 201 Invitation created
  • 401
  • 429
  • 502 The invitation email could not be delivered. The response message says whether the pending invitation was rolled back (safe to retry now) or is still present and blocking retries until it expires
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/team/invitations \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "example_email",
  "role": "editor",
  "shop_id": "uuid-here"
}'
DELETE

Revoke a shop invitation

/team/invitations/{id}

Parameters

  • id in path required

Request body

{
  shop_id: string (uuid)
}

Responses

  • 200 Invitation revoked
  • 401
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/team/invitations/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "shop_id": "uuid-here"
}'
PATCH

Update a shop member

/team/members/{id}

Request body

{
  shop_id: string (uuid)
  role?: "editor" | "client_viewer"
  permission_overrides?: object
}

Responses

  • 200 Member updated
  • 401
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/team/members/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "shop_id": "uuid-here",
  "role": "editor",
  "permission_overrides": {}
}'
DELETE

Remove a shop member

/team/members/{id}

Request body

{
  shop_id: string (uuid)
}

Responses

  • 200 Member removed
  • 401
  • 429
  • 503
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/team/members/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "shop_id": "uuid-here"
}'

Shops

GET

List organization shops

/shops

Responses

  • 200 Shop list
cURL
curl \
  https://app.drip-apex.com/api/v1/shops \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create a shop

/shops

Request body

{
  name: string
  domain: string
  platform: "shopify" | "hydrogen" | "shopware" | "woocommerce" | "centra" | "webflow" | "custom"
  plan?: "managed" | "self_serve"
  origin?: string,null
  currency?: "AED" | "AFN" | "ALL" | "AMD" | "ANG" | "AOA" | "ARS" | "AUD" | "AWG" | "AZN" | "BAM" | "BBD" | "BDT" | "BGN" | "BHD" | "BIF" | "BMD" | "BND" | "BOB" | "BOV" | "BRL" | "BSD" | "BTN" | "BWP" | "BYN" | "BZD" | "CAD" | "CDF" | "CHE" | "CHF" | "CHW" | "CLF" | "CLP" | "CNY" | "COP" | "COU" | "CRC" | "CUP" | "CVE" | "CZK" | "DJF" | "DKK" | "DOP" | "DZD" | "EGP" | "ERN" | "ETB" | "EUR" | "FJD" | "FKP" | "GBP" | "GEL" | "GHS" | "GIP" | "GMD" | "GNF" | "GTQ" | "GYD" | "HKD" | "HNL" | "HRK" | "HTG" | "HUF" | "IDR" | "ILS" | "INR" | "IQD" | "IRR" | "ISK" | "JMD" | "JOD" | "JPY" | "KES" | "KGS" | "KHR" | "KMF" | "KPW" | "KRW" | "KWD" | "KYD" | "KZT" | "LAK" | "LBP" | "LKR" | "LRD" | "LSL" | "LYD" | "MAD" | "MDL" | "MGA" | "MKD" | "MMK" | "MNT" | "MOP" | "MRU" | "MUR" | "MVR" | "MWK" | "MXN" | "MXV" | "MYR" | "MZN" | "NAD" | "NGN" | "NIO" | "NOK" | "NPR" | "NZD" | "OMR" | "PAB" | "PEN" | "PGK" | "PHP" | "PKR" | "PLN" | "PYG" | "QAR" | "RON" | "RSD" | "RUB" | "RWF" | "SAR" | "SBD" | "SCR" | "SDG" | "SEK" | "SGD" | "SHP" | "SLE" | "SOS" | "SRD" | "SSP" | "STN" | "SVC" | "SYP" | "SZL" | "THB" | "TJS" | "TMT" | "TND" | "TOP" | "TRY" | "TTD" | "TWD" | "TZS" | "UAH" | "UGX" | "USD" | "USN" | "UYI" | "UYU" | "UYW" | "UZS" | "VES" | "VND" | "VUV" | "WST" | "XAF" | "XCD" | "XCG" | "XDR" | "XOF" | "XPF" | "XSU" | "YER" | "ZAR" | "ZMW" | "ZWG"
}

Responses

  • 201 Shop created
  • 403
  • 409 The domain already has a live binding. Owner details are included only when the caller may see the owning shop.
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/shops \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "example_name",
  "domain": "example_domain",
  "platform": "shopify"
}'
GET

Get a shop

/shops/{id}

Responses

  • 200 Shop detail
  • 404
cURL
curl \
  https://app.drip-apex.com/api/v1/shops/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update a shop

/shops/{id}

Request body

{
  name?: string
  domain?: string
  origin?: string,null
  tier?: "self_managed" | "apex_managed" | "drip_managed" | "core" | "managed" | "enterprise"
  operator_enabled?: boolean
  holdout_pct?: number
  holdout_v1_enabled?: boolean
  currency?: "AED" | "AFN" | "ALL" | "AMD" | "ANG" | "AOA" | "ARS" | "AUD" | "AWG" | "AZN" | "BAM" | "BBD" | "BDT" | "BGN" | "BHD" | "BIF" | "BMD" | "BND" | "BOB" | "BOV" | "BRL" | "BSD" | "BTN" | "BWP" | "BYN" | "BZD" | "CAD" | "CDF" | "CHE" | "CHF" | "CHW" | "CLF" | "CLP" | "CNY" | "COP" | "COU" | "CRC" | "CUP" | "CVE" | "CZK" | "DJF" | "DKK" | "DOP" | "DZD" | "EGP" | "ERN" | "ETB" | "EUR" | "FJD" | "FKP" | "GBP" | "GEL" | "GHS" | "GIP" | "GMD" | "GNF" | "GTQ" | "GYD" | "HKD" | "HNL" | "HRK" | "HTG" | "HUF" | "IDR" | "ILS" | "INR" | "IQD" | "IRR" | "ISK" | "JMD" | "JOD" | "JPY" | "KES" | "KGS" | "KHR" | "KMF" | "KPW" | "KRW" | "KWD" | "KYD" | "KZT" | "LAK" | "LBP" | "LKR" | "LRD" | "LSL" | "LYD" | "MAD" | "MDL" | "MGA" | "MKD" | "MMK" | "MNT" | "MOP" | "MRU" | "MUR" | "MVR" | "MWK" | "MXN" | "MXV" | "MYR" | "MZN" | "NAD" | "NGN" | "NIO" | "NOK" | "NPR" | "NZD" | "OMR" | "PAB" | "PEN" | "PGK" | "PHP" | "PKR" | "PLN" | "PYG" | "QAR" | "RON" | "RSD" | "RUB" | "RWF" | "SAR" | "SBD" | "SCR" | "SDG" | "SEK" | "SGD" | "SHP" | "SLE" | "SOS" | "SRD" | "SSP" | "STN" | "SVC" | "SYP" | "SZL" | "THB" | "TJS" | "TMT" | "TND" | "TOP" | "TRY" | "TTD" | "TWD" | "TZS" | "UAH" | "UGX" | "USD" | "USN" | "UYI" | "UYU" | "UYW" | "UZS" | "VES" | "VND" | "VUV" | "WST" | "XAF" | "XCD" | "XCG" | "XDR" | "XOF" | "XPF" | "XSU" | "YER" | "ZAR" | "ZMW" | "ZWG"
}

Responses

  • 200 Shop updated
  • 403
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/shops/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
POST

Pre-bind a Shopware store to an Apex shop

/shops/{id}/shopware/prebind

Request body

{
  shopUrl: string (uri)
  environmentKey?: string = "production"
}

Responses

  • 200 Existing binding returned
  • 201 Pending binding created
  • 400
  • 401
  • 403
  • 409
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/shops/exp_123/shopware/prebind \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "shopUrl": "https://example.com",
  "environmentKey": "example_environmentKey"
}'
GET

Get auto-stop settings

/shops/{id}/auto-stop

Responses

  • 200 Settings
cURL
curl \
  https://app.drip-apex.com/api/v1/shops/exp_123/auto-stop \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update auto-stop settings

/shops/{id}/auto-stop

Request body

{
  enabled?: boolean
  mode?: "off" | "fixed_horizon_planned_end" | "sequential_significance"
  min_runtime_minutes?: integer
  sequential?: object
  fixed_horizon?: object
}

Responses

  • 200 Settings updated
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/shops/exp_123/auto-stop \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
GET

Get testing-defaults settings

/shops/{id}/testing-defaults

Responses

  • 200 Settings
cURL
curl \
  https://app.drip-apex.com/api/v1/shops/exp_123/testing-defaults \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update testing-defaults settings

/shops/{id}/testing-defaults

Request body

{
  significanceLevel?: number
  statisticalPower?: number
  sequentialTestingEnabled?: boolean
}

Responses

  • 200 Settings updated
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/shops/exp_123/testing-defaults \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "significanceLevel": 1,
  "statisticalPower": 1,
  "sequentialTestingEnabled": false
}'
GET

Get guardian settings

/shops/{id}/guardian

Responses

  • 200 Settings
cURL
curl \
  https://app.drip-apex.com/api/v1/shops/exp_123/guardian \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update guardian settings

/shops/{id}/guardian

Request body

{
  enabled?: boolean
  pause_on_broken?: boolean
  pause_on_harm?: boolean
  alert_on_data_quality?: boolean
  delivery_drift?: object
  revenue_loss?: object,null
}

Responses

  • 200 Settings updated
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/shops/exp_123/guardian \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
GET

Get the store profile

/shops/{id}/store-profile

Responses

  • 200 The complete dashboard Store Profile contract. When the store-profile schema is not yet migrated, the route degrades to `{ schemaReady: false }` with HTTP 200 instead of failing.
  • 503 Store profile temporarily unavailable (database under pressure); retry shortly.
cURL
curl \
  https://app.drip-apex.com/api/v1/shops/exp_123/store-profile \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Review a store-profile fact

/shops/{id}/store-profile/facts/{factId}

Request body

{
  status: "suggested" | "confirmed" | "rejected" | "stale"
  claim?: string
  value?: any
}

Responses

  • 200 Fact reviewed
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/shops/exp_123/store-profile/facts/fact_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "suggested",
  "claim": "example_claim"
}'
POST

Review a semantic finding

/shops/{id}/store-profile/findings/review

Request body

{
  key: string
  claim: string
  status?: string
  title?: string
  category?: string
  source?: string
  confidence?: number
  value?: any
}

Responses

  • 200 Finding reviewed
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/shops/exp_123/store-profile/findings/review \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "key": "example_key",
  "claim": "example_claim"
}'
POST

Start a store-profile learning run

/shops/{id}/store-profile/learning-runs

Request body

{
  trigger?: string = "manual"
  sources?: string[]
  scope?: string[]
}

Responses

  • 201 Learning run queued
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/shops/exp_123/store-profile/learning-runs \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "trigger": "example_trigger",
  "sources": [],
  "scope": []
}'
GET

Get engine state and guardrails

/shops/{id}/engine

Parameters

  • id in path required

Responses

  • 200 Engine state
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/shops/exp_123/engine \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Get engine guardrails

/shops/{id}/engine/guardrails

Parameters

  • id in path required

Responses

  • 200 Engine guardrails
  • 400
  • 401
  • 403
  • 404
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/shops/exp_123/engine/guardrails \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update engine guardrails with optimistic concurrency

/shops/{id}/engine/guardrails

Parameters

  • id in path required

Request body

{
  expected_version: integer
  allow?: object
  auto_launch?: object
  surfaces?: object
  segments?: any
  max_concurrent?: integer
  max_per_page?: integer
}

Responses

  • 200 Updated engine guardrails
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/shops/exp_123/engine/guardrails \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "expected_version": 1
}'
POST

Start engine

/shops/{id}/engine/start

Parameters

  • id in path required

Responses

  • 200 Engine state updated
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/shops/exp_123/engine/start \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Pause engine

/shops/{id}/engine/pause

Parameters

  • id in path required

Responses

  • 200 Engine state updated
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/shops/exp_123/engine/pause \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Stop engine

/shops/{id}/engine/stop

Parameters

  • id in path required

Responses

  • 200 Engine state updated
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/shops/exp_123/engine/stop \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Approve engine proposal

/shops/{id}/engine/proposals/{pid}/approve

Parameters

  • id in path required
  • pid in path required

Responses

  • 200 Engine proposal approve decision recorded
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/shops/exp_123/engine/proposals/p_123/approve \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Reject engine proposal

/shops/{id}/engine/proposals/{pid}/reject

Parameters

  • id in path required
  • pid in path required

Request body

{
  reason: string
}

Responses

  • 200 Engine proposal reject decision recorded
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/shops/exp_123/engine/proposals/p_123/reject \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "example_reason"
}'
POST

Veto engine proposal

/shops/{id}/engine/proposals/{pid}/veto

Parameters

  • id in path required
  • pid in path required

Responses

  • 200 Engine proposal veto decision recorded
  • 400
  • 401
  • 403
  • 404
  • 409
  • 422
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/shops/exp_123/engine/proposals/p_123/veto \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Roll a certified Engine winner out to 100% of traffic

/shops/{id}/engine/interventions/{iid}/rollout

Sends all eligible traffic to the winning variation, freezes the certified interval, and starts the decay watch. The program holdout is untouched.

Parameters

  • id in path required
  • iid in path required

Request body

{
  expected_updated_at: string (date-time)
}

Responses

  • 200 Engine intervention rolled out
  • 400
  • 401
  • 403
  • 404
  • 409 Rollout refused
  • 422
  • 429
  • 503 Either the certified measurement could not be read (rollout refused, retriable) or the rate-limiting backend is unavailable. Both are plain error envelopes; only the first carries a rollout `code`.
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/shops/exp_123/engine/interventions/i_123/rollout \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "expected_updated_at": "example_expected_updated_at"
}'

Audit logs

GET

List audit logs for an authorized shop with a user API key

/shops/{id}/audit-logs

Parameters

  • entity_type in query
  • entity_id in query
  • limit in query
  • offset in query

Responses

  • 200 Audit log page
  • 403
  • 404
cURL
curl \
  https://app.drip-apex.com/api/v1/shops/exp_123/audit-logs \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List audit logs

/audit-logs

Parameters

  • entity_type in query
  • entity_id in query
  • limit in query
  • offset in query

Responses

  • 200 Audit log page
  • 403
cURL
curl \
  https://app.drip-apex.com/api/v1/audit-logs \
  -H "Authorization: Bearer <apex-secret-key>"

Analytics

GET

Show entry and exit page analytics

/analytics/entry-exit

Parameters

  • days in query

Responses

  • 200 Analytics data
  • 401
  • 403
  • 429
  • 503 Analytics is temporarily unavailable
cURL
curl \
  https://app.drip-apex.com/api/v1/analytics/entry-exit \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Show geography and device analytics

/analytics/geo

Parameters

  • days in query

Responses

  • 200 Analytics data
  • 401
  • 403
  • 429
  • 503 Analytics is temporarily unavailable
cURL
curl \
  https://app.drip-apex.com/api/v1/analytics/geo \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Show page analytics

/analytics/pages

Parameters

  • days in query
  • planningDays in query - Planning window in days (planning_days is also accepted)
  • limit in query

Responses

  • 200 Analytics data
  • 401
  • 403
  • 429
  • 503 Analytics is temporarily unavailable
cURL
curl \
  https://app.drip-apex.com/api/v1/analytics/pages \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Show realtime analytics

/analytics/realtime

Responses

  • 200 Analytics data
  • 401
  • 403
  • 429
  • 503 Analytics is temporarily unavailable
cURL
curl \
  https://app.drip-apex.com/api/v1/analytics/realtime \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Show session analytics

/analytics/sessions

Parameters

  • days in query

Responses

  • 200 Analytics data
  • 401
  • 403
  • 429
  • 503 Analytics is temporarily unavailable
cURL
curl \
  https://app.drip-apex.com/api/v1/analytics/sessions \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Show dashboard analytics stats

/analytics/stats

Parameters

  • days in query
  • shop_currency in query

Responses

  • 200 Analytics data
  • 400
  • 401
  • 403
  • 422
  • 429
  • 503 Analytics is temporarily unavailable
cURL
curl \
  https://app.drip-apex.com/api/v1/analytics/stats \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Suggest goals and funnels

/analytics/suggest-goals

Requires a secret API key with the analytics:read scope. The endpoint only reads analytics and returns suggestions — it creates no goals — but it spends model budget, so publishable keys receive 403 Forbidden and a per-shop 24-hour spend guard applies on top of the normal API rate limit.

Responses

  • 200 Suggested goals and funnels
  • 401
  • 403
  • 413 Request body is too large
  • 429
  • 502 The suggestion model returned unusable output
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/analytics/suggest-goals \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Show analytics timeseries

/analytics/timeseries

Parameters

  • days in query

Responses

  • 200 Analytics data
  • 401
  • 403
  • 422
  • 429
  • 503 Analytics is temporarily unavailable
cURL
curl \
  https://app.drip-apex.com/api/v1/analytics/timeseries \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Show traffic sources

/analytics/traffic

Parameters

  • days in query

Responses

  • 200 Analytics data
  • 401
  • 403
  • 429
  • 503 Analytics is temporarily unavailable
cURL
curl \
  https://app.drip-apex.com/api/v1/analytics/traffic \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Show URL inventory

/analytics/url-inventory

Returns a shaped Tinybird pageview URL inventory for the API key's shop. Requires a secret API key with analytics:read.

Parameters

  • days in query
  • host in query
  • pathContains in query
  • limit in query
  • offset in query

Responses

  • 200 URL inventory
  • 401
  • 403
  • 429
  • 503 Analytics is temporarily unavailable
cURL
curl \
  https://app.drip-apex.com/api/v1/analytics/url-inventory \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Show daily visitor series

/analytics/visitor-series

Parameters

  • days in query

Responses

  • 200 Daily visitors and pageviews
  • 401
  • 403
  • 429
  • 503 Analytics is temporarily unavailable
cURL
curl \
  https://app.drip-apex.com/api/v1/analytics/visitor-series \
  -H "Authorization: Bearer <apex-secret-key>"

Brand

GET

Get brand context

/brand-context

Returns the compiled shop brand context for external agents and developer workflows. Internal Apex notes are never included.

Responses

  • 200 Compiled brand context
  • 401 Unauthorized
  • 403 API key is missing experiment read permission
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/brand-context \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Read consent gating settings

/consent

Responses

  • 200 Consent settings
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/consent \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update consent gating settings

/consent

Request body

{
  applyCanonicalSplit?: "true"
  consentMode?: object
}

Responses

  • 200 Updated consent settings
  • 400
  • 401
  • 403
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/consent \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "applyCanonicalSplit": true,
  "consentMode": {}
}'

Environments

GET

List runtime environments and domain mappings

/environments

Responses

  • 200 Environment settings
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/environments \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update runtime environments and domain mappings

/environments

Request body

{
  environments?: Environments
  expected_version?: string,null (date-time)
}

Responses

  • 200 Updated environment settings and edge precompile outcome
  • 400 The environment patch is invalid, including when the active key is absent from the effective environment items.
  • 401
  • 403
  • 409 Runtime settings changed since the supplied version was read; re-read and retry.
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/environments \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'

Funnels

GET

Run funnel analysis

/funnels/{id}/run

Parameters

  • id in path required
  • days in query

Responses

  • 200 Funnel run
  • 400
  • 401
  • 403
  • 404
  • 429
  • 502 Analysis unavailable
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/funnels/exp_123/run \
  -H "Authorization: Bearer <apex-secret-key>"

Goals

GET

List goals

/goals

Returns a paginated list of goals for the shop.

Parameters

  • cursor in query
  • include_archived in query - Include archived goals.
  • limit in query

Responses

  • 200 Paginated list of goals
  • 401 Unauthorized
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/goals \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Create goal

/goals

Creates a new goal. Click goals require page_id plus selector or text_match. Pageview goals require page_id or url_pattern. Custom goals require event_name. Line-item filters are accepted for revenue goals and custom checkout_started/add_to_cart funnel-event goals.

Request body

{
  capture?: any
  count_once?: boolean = false
  event_name?: any
  filter?: any
  measurement?: "conversion" | "value"
  name: string
  page_id?: any
  selector?: any
  text_match?: any
  type: "click" | "pageview" | "custom" | "revenue"
  url_pattern?: any
  value_property?: any
  value_unit?: any
}

Responses

  • 201 Goal created
  • 400 Validation error
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/goals \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "example_name",
  "type": "click"
}'
GET

Get goal

/goals/{id}

Returns a single goal by ID.

Parameters

  • id in path required

Responses

  • 200 Goal details
  • 404 Goal not found
cURL
curl \
  https://app.drip-apex.com/api/v1/goals/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update goal

/goals/{id}

Partially updates a goal. Line-item filters are accepted for revenue goals and custom checkout_started/add_to_cart funnel-event goals. Custom goals may not listen on reserved wire event names (purchase, pageview, ...): the resulting type/event_name combination is validated against the stored row and rejected with 400 (funnel-event goal names are the sanctioned exception).

Parameters

  • id in path required

Request body

{
  capture?: any
  count_once?: boolean
  event_name?: any
  filter?: any
  measurement?: "conversion" | "value"
  name?: string
  page_id?: any
  selector?: any
  text_match?: any
  type?: "click" | "pageview" | "custom" | "revenue"
  url_pattern?: any
  value_property?: any
  value_unit?: any
}

Responses

  • 200 Goal updated
  • 404 Goal not found
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/goals/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE

Archive goal

/goals/{id}

Archives a goal while preserving its experiment and personalization links.

Parameters

  • id in path required

Responses

  • 200 Goal deleted
  • 404 Goal not found
cURL
curl -X DELETE \
  https://app.drip-apex.com/api/v1/goals/exp_123 \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Restore goal

/goals/{id}/restore

Parameters

  • id in path required

Responses

  • 200 Goal restored
  • 404 Goal not found
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/goals/exp_123/restore \
  -H "Authorization: Bearer <apex-secret-key>"

Inbox

GET

List inbox messages

/inbox/messages

Parameters

  • experiment_id in query

Responses

  • 200 Inbox messages
  • 403
cURL
curl \
  https://app.drip-apex.com/api/v1/inbox/messages \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Send an inbox message

/inbox/messages

Request body

{
  body: string
  experiment_id?: any
  thread_type?: "account" | "experiment"
}

Responses

  • 201 Message created
  • 400
  • 403
  • 404
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/inbox/messages \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "body": "example_body",
  "thread_type": "account"
}'
POST

Mark inbox channels read

/inbox/read-state

Request body

unknown

Responses

  • 200 Read state updated
  • 400
  • 403
  • 404
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/inbox/read-state \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{}'

Install Domains

GET

Read install domains and storefront origins

/install-domains

Responses

  • 200 Install domains
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/install-domains \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Replace install domains

/install-domains

Request body

{
  domains: string[]
  ifRevision?: string
}

Responses

  • 200 Updated install domains and edge precompile outcome
  • 400
  • 401
  • 403
  • 409 Install domains changed since the supplied revision was read; re-read and retry.
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/install-domains \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "domains": [],
  "ifRevision": "example_ifRevision"
}'

User keys

GET

Inspect the current user API key identity

/me

Responses

  • 200 User key identity and live organization role
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/me \
  -H "Authorization: Bearer <apex-secret-key>"
GET

List every organization and shop available to a user API key

/me/context

Responses

  • 200 User key context with effective organization and shop roles
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/me/context \
  -H "Authorization: Bearer <apex-secret-key>"

Roadmap

GET

List approved roadmap ideas

/roadmap/approved

Returns approved backlog/roadmap ideas ready to build in Apex. This is the API used by `apex roadmap approved`.

Parameters

  • limit in query
  • cursor in query
  • q in query - Search title, description, hypothesis, brief, and research notes.
  • has_experiment in query - When false, only returns approved ideas without a linked experiment. When true, only returns ideas with a linked experiment.

Responses

  • 200 Approved roadmap ideas
  • 401 Unauthorized
  • 403 API key is missing backlog read permission
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/roadmap/approved \
  -H "Authorization: Bearer <apex-secret-key>"
GET

Get roadmap build handoff

/roadmap/items/{id}/handoff

Returns the full build brief for an approved roadmap item, including hypothesis, target page, visual references, scoring, and Apex CLI workspace commands.

Parameters

  • id in path required

Responses

  • 200 Roadmap build handoff
  • 401 Unauthorized
  • 403 API key is missing backlog read permission
  • 404 Roadmap item not found
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/roadmap/items/exp_123/handoff \
  -H "Authorization: Bearer <apex-secret-key>"

Runtime settings

GET

Read public runtime settings

/runtime-settings

Responses

  • 200 Parsed runtime settings with shop identity and opaque version
  • 401
  • 403
  • 429
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/runtime-settings \
  -H "Authorization: Bearer <apex-secret-key>"
PATCH

Update data layer triggers, setup capture, or project code

/runtime-settings

Request body

{
  dataLayerTriggers?: DataLayerTrigger[]
  expectedVersion?: string,null (date-time)
  projectCode?: object
  setupCapture?: object
}

Responses

  • 200 Updated runtime settings and precompile result
  • 400
  • 401
  • 403
  • 409
  • 429
  • 503
cURL
curl -X PATCH \
  https://app.drip-apex.com/api/v1/runtime-settings \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "dataLayerTriggers": [],
  "projectCode": {},
  "setupCapture": {}
}'
POST

Apply a server-owned runtime integration recipe

/runtime-settings/recipes

Request body

{
  expectedVersion?: string,null (date-time)
  params?: object
  recipeId: "customDataLayerPurchase" | "ga4Ecommerce"
}

Responses

  • 200 Updated runtime settings and precompile result
  • 400
  • 401
  • 403
  • 409
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/runtime-settings/recipes \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "params": {},
  "recipeId": "customDataLayerPurchase"
}'

SOS

POST

Create SOS ticket

/sos

Creates a customer bug report or help request for shop API keys. User API keys belonging to a DRIP platform administrator may also create internal SOS types.

Request body

{
  affected_url?: any
  description: string
  expected_behavior?: string
  experiment_id?: any
  idempotency_key?: string
  loom_url?: any
  reproduction_steps?: any
  sub_class?: any
  type: "full_handover" | "design" | "development" | "qa" | "config" | "bug" | "help"
}

Responses

  • 200 Reused internal SOS ticket or deduplicated customer ticket receipt
  • 201 Internal SOS ticket or customer ticket created
  • 401 Unauthorized
  • 403 API key is missing permission or requested an internal SOS type
  • 429 Rate limit exceeded
  • 502 Jira create failed
  • 503 SOS is disabled
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/sos \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "description": "example_description",
  "type": "full_handover"
}'
GET

List my SOS tickets

/sos/mine

Lists SOS tickets created by the current API key.

Responses

  • 200 SOS tickets
  • 401 Unauthorized
  • 403 API key is missing experiment read permission
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/sos/mine \
  -H "Authorization: Bearer <apex-secret-key>"

Tracking

GET

Discover the observed tracking schema

/tracking/discovery

Aggregates consented-session QA diagnostic events (qa_mode=1) and normal-traffic pageview denominators (qa_mode=0) for the authenticated API key's shop.

Parameters

  • minutes in query
  • limit in query

Responses

  • 200 Observed tracking schema report with URL push/pageview counts, timing percentiles, type-collision flags, and ranked storage keys
  • 401 Unauthorized
  • 403 API key is missing experiment read permission
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/tracking/discovery \
  -H "Authorization: Bearer <apex-secret-key>"
POST

Simulate data-layer triggers

/tracking/simulate-trigger

Pure dry run of dataLayerTriggers against payloads. Does not persist or emit events.

Request body

{
  payloads: array
  triggers: object[]
}

Responses

  • 200 Side-effect-free simulation verdict
  • 400
  • 401
  • 403
  • 413 Request body exceeds 64KB
  • 429
  • 503
cURL
curl -X POST \
  https://app.drip-apex.com/api/v1/tracking/simulate-trigger \
  -H "Authorization: Bearer <apex-secret-key>" \
  -H "Content-Type: application/json" \
  -d '{
  "payloads": [],
  "triggers": []
}'
GET

Verify live tracking events

/tracking/verify

Returns recent Tinybird events for the API key's shop so agents can verify revenue, pageview, and custom tracking setup from the CLI.

Parameters

  • minutes in query
  • limit in query
  • experiment_id in query
  • event_type in query - Comma-separated event type filter.

Responses

  • 200 Tracking verification summary
  • 401 Unauthorized
  • 403 API key is missing experiment read permission
  • 429 Rate limit exceeded
  • 503
cURL
curl \
  https://app.drip-apex.com/api/v1/tracking/verify \
  -H "Authorization: Bearer <apex-secret-key>"