> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pcnaid.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Apex Brand & Event Mgmt API overview

> Public, webhook, app-proxy, and developer API endpoints for Apex Brand & Event Mgmt.

# Apex Brand & Event Mgmt API overview

This page documents the externally reachable HTTP surface of Apex Brand & Event Mgmt: the public routes, the Shopify webhook handler, the signed storefront app proxy, and the Advanced developer API. Authenticated admin routes under `/app` are not public integration points.

## Public routes

### `GET /`

When a `shop` or `host` query parameter is present, redirects to `/app` with the original query string. With no Shopify context, returns an HTTP 200 JSON health-style response instead of entering an authentication loop.

### `GET /healthz`

Returns HTTP 200 JSON with a status and release identifier when the database probe succeeds. A database failure returns HTTP 503 with a generic error and never includes the underlying database error message. Responses carry no-store.

### `GET /privacy` and `GET /terms`

Issue permanent HTTP 301 redirects to the centralized Pcnaid documentation at the privacy and terms pages. They require no Shopify session.

### `GET /support`

A public support portal that requires no Shopify session. Its document responses use a short public cache policy.

## Shopify webhook handler — `POST /webhooks`

The app subscribes to Shopify webhooks and verifies the raw-body HMAC before any database or queue operation. Subscribed topics include `app/uninstalled`, `shop/update`, `app_subscriptions/update`, and the mandatory compliance topics `customers/data_request`, `customers/redact`, and `shop/redact`. Duplicate deliveries are acknowledged without repeating their effect, and processing failures return an error so Shopify retries.

## Advanced developer API — `GET`/`POST /api/v1/campaigns`

Available on the Advanced plan. Supply `Authorization: Bearer <token>` using a one-time token generated in the Integrations screen.

* `GET` returns at most 100 campaign summaries plus the total.
* `POST` accepts a bounded JSON object with `name`, ISO `startAt` and `endAt`, 1–250 Shopify Product GIDs, and an optional discount. It resolves the current shop timezone and every product through Shopify, rejecting missing or non-active products, and creates a draft. API clients cannot bypass the explicit in-admin scheduling, approval, and provider-scope workflow.
* Invalid or downgraded tokens return `401` with `WWW-Authenticate: Bearer`. Unsupported methods and media types return `405`/`415`, oversized bodies return `413`, malformed JSON returns `400`, and schema errors return `422`.

### Create a campaign

Replace `<token>` with your one-time bearer token and replace the sample Product GID with an active product from the authenticated shop. Both timestamps must be in the future, and `endAt` must be later than `startAt`.

```bash theme={null}
curl --request POST \
  --url 'https://campaign-conductor.shpfy.pndsvcs.com/api/v1/campaigns' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Holiday launch",
    "startAt": "2030-11-20T15:00:00Z",
    "endAt": "2030-11-27T15:00:00Z",
    "productGids": [
      "gid://shopify/Product/1234567890"
    ],
    "discount": {
      "code": "HOLIDAY20",
      "type": "PERCENTAGE",
      "value": 20,
      "appliesToAll": false
    }
  }'
```

The request body uses this schema:

| Property | Type | Required | Constraints |
| - | - | :-: | - |
| `name` | string | Yes | Trimmed; 1–120 characters. |
| `startAt` | string | Yes | ISO 8601 date-time in the future. |
| `endAt` | string | Yes | ISO 8601 date-time later than `startAt`. |
| `productGids` | string array | Yes | 1–250 values in `gid://shopify/Product/<numeric-id>` format. Every product must exist and be active in the authenticated shop. |
| `discount` | object | No | Omit the property to create a campaign without a discount. |
| `discount.code` | string | With `discount` | Trimmed; 1–255 characters. |
| `discount.type` | string | With `discount` | `PERCENTAGE` or `FIXED_AMOUNT`. |
| `discount.value` | number | With `discount` | Greater than `0`; a percentage cannot exceed `100`. |
| `discount.appliesToAll` | boolean | No | Defaults to `false`. |

The top-level object rejects unknown properties. A successful request returns HTTP `201` with the new campaign ID and `"status": "DRAFT"`.

### Outbound lifecycle webhooks

Configured from the Integrations screen, outbound webhooks use `x-campaign-conductor-event` and `x-campaign-conductor-signature: sha256=<hex HMAC>` headers over the exact JSON body. Event IDs are stable `<campaignId>:<eventType>` values so receivers can deduplicate ambiguous retries. Only public HTTPS port 443 endpoints are accepted; DNS is checked before storage and delivery, and redirects are refused.

## Storefront app proxy — `GET /api/proxy/intent.js`

Serves the Advanced smart-intent popup JavaScript through the signed Shopify App Proxy. The shop is derived from the signed proxy request; unsigned requests return `401`. The storefront requests this route through the shop-owned `/apps/campaign-conductor/intent.js` URL, loaded by the smart-intent-popup theme app embed. The route remains inert unless an entitled Advanced popup campaign is running.

## One-click unsubscribe — `GET`/`POST /api/proxy/unsubscribe`

The HMAC token binds shop, normalized email, and campaign. `POST` implements RFC 8058 one-click and is the only method that writes suppression. `GET` verifies the capability and renders a human confirmation form, preventing mail scanners from silently unsubscribing a recipient.

## Resend delivery feedback — `POST /api/webhooks/resend`

Accepts only JSON bodies up to 256 KiB with verified `svix-id`, `svix-timestamp`, and `svix-signature` headers before tenant access. Duplicate calls are idempotent. Accepted delivery-state events include sent, delivered, delivery delayed, failed, bounced, complained, and suppressed.

## Web pixel collection — `POST`/`OPTIONS /api/web-pixel`

Receives consent-aware storefront events from the web pixel extension. It accepts only JSON up to 128 KiB and the nine subscribed Shopify event names. A shop-scoped pixel HMAC and installed session are required. Events older than seven days or more than five minutes in the future return `400`; a shop above the rate window receives `429`. `(shop,eventId)` is unique, so provider replays have no second effect.

## Authentication and scopes

Requests use Shopify online user sessions for authenticated admin work, while background jobs and webhooks keep the separately stored offline session. Billing changes and confirmations require the store account owner. Campaign operations are scoped to `session.shop`; cross-tenant campaign IDs are concealed as `404`. The app requests Shopify scopes for product and publication publishing, discounts, customer segments and pixels, metaobjects, and live theme scheduling. See the [quickstart](https://docs.pcnaid.com/nodes/shopify/apex-brand-event-mgmt/developer/quickstart.md) for the full scope list.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.