Pack Experience · Agency API v1
Your frontend. Onpack’s promotion engine.
Build and host a completely custom campaign. Onpack authenticates collectors, validates their packs, runs the draw and delivers prizes.
What you receive
The brand opens Promotion → Experience setup, selects Built by my agency, and creates separate sandbox and production keys. Each opx_… key reaches exactly one promotion and expires after 90 days. No dashboard account is needed. Ask the brand to share keys securely.
Keep both keys and consumer session tokens on your backend, in a secrets manager / server-side session store. Never embed them in JavaScript, JSON sent to the browser, analytics or URLs. The API does not provide browser CORS access. Protect your own entry endpoint against CSRF and rate-limit it.
This first version supports instant win, code unlock and content promotions, using Onpack collector sign-in. Custom SSO, collection mechanics and an agency team-management portal are not part of this API.
1. Read the campaign
curl https://onpack.io/api/experience/v1/campaign \
-H "Authorization: Bearer $ONPACK_AGENCY_KEY"
The response includes campaign (name, dates, mechanic, brand, copy and public prize names), environment, authorize_url and sandbox_scenarios. It does not expose customers, pool codes, draw seeds or partner credentials.
2. Build against deterministic sandbox outcomes
curl https://onpack.io/api/experience/v1/sessions \
-H "Authorization: Bearer $ONPACK_SANDBOX_KEY" \
-H "Content-Type: application/json" \
-d '{"scenario":"won"}'
HTTP 201 returns a session_token, expires_at, campaign, country-specific terms, eligibility, entry and sandbox: true. Store the token on your server. Create one session for each of won, lost, pending, failed, ineligible and already_entered, then POST an entry for each.
curl https://onpack.io/api/experience/v1/session/entry \
-H "Authorization: Bearer $ONPACK_SANDBOX_KEY" \
-H "X-Onpack-Session: $ONPACK_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'
Sandbox results are synthetic: they do not require a pack or collector, run a real draw, reserve stock, send emails or create analytics entries. Consent and live-campaign guards are enforced in production. The brand’s checklist records API coverage, not visual approval of your website.
3. Connect the production browser journey
The callback URL also serves as your public campaign landing page: when opened without an Onpack query parameter, show the campaign and ask the visitor to scan a participating pack. The collector’s Promotions list links here once the experience is approved and live. Onpack’s private preview and test packs continue to use the hosted fallback.
- The customer scans the existing pack QR and signs in to Onpack. Recall notices are handled before any hand-off. No promotion entry is created yet.
- Onpack redirects to the brand-approved HTTPS callback with
?onpack_request=…. This short-lived request is bound to that collector and pack. - Your backend generates a cryptographically random
state(32–128 base64url characters) and PKCEcode_verifier(43–128 unreserved characters). Store both in a server-side transaction tied to this browser’s secure, HttpOnly, SameSite=Lax session cookie. Do not accept state or a verifier supplied by the browser. - Compute
code_challenge = BASE64URL(SHA256(code_verifier)), without padding. Redirect toauthorize_urlwithrequest_token,state,code_challengeandcode_challenge_method=S256. - Onpack asks the signed-in customer to continue to the campaign. After confirmation it redirects to the same approved callback with
?onpack_code=…&state=…. - Require the original browser cookie and compare state in constant time. Consume the stored transaction once, then exchange the code with your stored verifier from your server. Reject unsolicited or mismatched callbacks.
curl https://onpack.io/api/experience/v1/sessions \
-H "Authorization: Bearer $ONPACK_PRODUCTION_KEY" \
-H "Content-Type: application/json" \
-d '{"authorization_code":"CODE_FROM_CALLBACK","code_verifier":"YOUR_STORED_PKCE_VERIFIER"}'
The request and authorization code each expire after five minutes; the authorization code is single-use. Consumer sessions last 30 minutes and are bound to the key that exchanged them. If exchange fails after a network interruption, restart from the pack scan; never guess a result. Keep callback pages free of third-party scripts, redact these query parameters from logs, send Cache-Control: no-store and Referrer-Policy: same-origin, and immediately redirect to a clean URL after processing. This policy suppresses external referrers while preserving the Origin header required by same-origin CSRF checks.
4. Show the rules, then submit one entry
Render terms.text, terms.url and every terms.links item as text / safe links, not raw HTML. When terms.required is true, obtain explicit acceptance. When terms.minimum_age is present, also obtain confirmation of that minimum age. Do not preselect consent or combine it with optional marketing consent. Send the exact terms.version returned for this session.
curl https://onpack.io/api/experience/v1/session/entry \
-H "Authorization: Bearer $ONPACK_PRODUCTION_KEY" \
-H "X-Onpack-Session: $ONPACK_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"consent":{"accepted":true,"age_confirmed":true,"terms_version":"VERSION_FROM_SESSION"}}'
Do not send consumer IDs, email addresses, raw pack codes or a country. Identity and country come from the Onpack browser journey, not your server’s IP. A missing or disallowed country cannot enter a restricted campaign. Onpack enforces repeat-entry protection, pack ownership, dates, budget, eligibility, odds and stock; your animations must reveal the returned result, never choose it.
Retries for the same collector and pack return the existing entry. A different collector cannot get that pack’s result. The existing Onpack Rewards page remains the customer’s durable prize wallet; resolve campaign.rewards_path against the Onpack API origin to link to it.
5. Render outcomes and delivery
| Response | Your website |
|---|---|
200 · entry.state: won | Show the prize, delivered codes and optional redemption_url. |
200 · lost | Show the non-winning result. |
200 · pending | The customer won; delivery is processing. Poll the session with backoff. |
200 · failed | The customer still won. Show a delivery delay; do not redraw. The brand can retry delivery in Onpack. |
403 · ineligible | Explain that the campaign is unavailable in this location. |
409 · already_entered | This pack cannot be entered again. No other collector’s result is disclosed. |
422 · consent_required | Refresh the session’s current terms and request acceptance. |
401 · invalid_session | Ask the customer to rescan; never retry with a different customer identity. |
| 409/410 · unavailable | Show a clear unavailable state and a route back to Onpack Rewards. |
429 · rate_limited | Respect Retry-After and back off. |
GET /api/experience/v1/session, with the same two headers, returns refreshed terms and the latest entry/delivery state. Poll pending delivery at 2, 5, 10, then 30-second intervals; stop on delivered/failed, expired session or unavailable integration. Rate limits are 60 requests per minute per consumer session and 3,000 per minute per campaign key. These are abuse ceilings, not a throughput SLA.
Launch and rollback
Give the brand your preview and production callback URLs (HTTPS, no query string or fragment). After all six sandbox calls, the brand reviews your responsive UI, legal copy, accessibility, failure states and hosting, then explicitly approves the integration. The promotion must also be live. Test codes remain in Onpack’s tester flow; they are never routed into production agency sessions.
Changing either URL invalidates approval and the checklist. Pausing routing or revoking the last production key returns subsequent scans to the Onpack page; it does not erase entries or prizes. Keep that fallback page ready. An outage of the agency host is not detected automatically: arrange monitoring and a rollback owner with the brand. Rotate keys before expiry, verify the new key, then revoke the old one.
All backend work remains under the brand’s existing Onpack rules. This API does not grant an agency permission to change odds, create prizes, export customers or administer the brand.