{"info":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","description":"<html><head></head><body><p>Server-to-server APIs for integrating with Snapplify — payments, catalogue sync, orders, vouchers, user provisioning, and single sign-on.</p>\n<h2 id=\"apis-in-this-collection\">APIs in this collection</h2>\n<ul>\n<li><strong>Snapplify Pay</strong> — hosted payment flow across multiple gateways.</li>\n<li><strong>Snapplify Catalogue API</strong> — receive pushed asset metadata as your catalogue changes   (Snapplify posts into your endpoint).</li>\n<li><strong>Snapplify Voucher API</strong> — issue vouchers that entitle users to specific assets.</li>\n<li><strong>Snapplify Order API</strong> — create and track orders.</li>\n<li><strong>Snapplify Auth</strong> — OAuth 2.0 / OIDC sign-in and User Info.</li>\n<li><strong>Snapplify Subscription API</strong> — plan templates and per-user grants.</li>\n<li><strong>Snapplify Access API</strong> — user provisioning via upsert-by-externalId (SSO / directory sync).</li>\n</ul>\n<h2 id=\"getting-started\">Getting started</h2>\n<ol>\n<li><strong>Import</strong> this collection.</li>\n<li><strong>Select the <code>Production</code> environment</strong> (top-right in Postman).</li>\n<li><strong>Fill in your credentials</strong> in the environment: <code>api_key</code>, <code>client_id</code>, <code>client_secret</code>, <code>redirect_uri</code>, <code>pay_client</code>, <code>pay_secret</code>. Contact your Snapplify integration lead if you don't have these yet.</li>\n<li>For OAuth flows, open <strong>Snapplify Auth / User Info</strong> and click <strong>Get New Access Token</strong> — Postman's OAuth 2.0 helper runs the full authorize → token flow for you.</li>\n</ol>\n<h2 id=\"authentication\">Authentication</h2>\n<p>Three schemes, applied per-API:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Scheme</th>\n<th>Used by</th>\n<th>How</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>API Key</strong> (<code>apiKey</code> header)</td>\n<td>Subscription, Access, Order, Voucher</td>\n<td>Collection-level auth — set <code>{{api_key}}</code> in the env once</td>\n</tr>\n<tr>\n<td><strong>OAuth 2.0</strong> (authorization code)</td>\n<td>User Info</td>\n<td>Postman's built-in OAuth 2.0 helper</td>\n</tr>\n<tr>\n<td><strong>Query-string</strong> (<code>client</code> + <code>secret</code>)</td>\n<td>Pay</td>\n<td>Set <code>{{pay_client}}</code> / <code>{{pay_secret}}</code> in the env</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"base-urls-production\">Base URLs (Production)</h2>\n<ul>\n<li><code>https://api.snapplify.com</code> — Subscription, Access, Order, Voucher</li>\n<li><code>https://auth.snapplify.com</code> — Auth flow + User Info</li>\n<li><code>https://pay.snapplify.com</code> — Pay</li>\n</ul>\n<h2 id=\"webhooks-snapplify-→-your-endpoint\">Webhooks (Snapplify → your endpoint)</h2>\n<p>Two flows where Snapplify POSTs to an endpoint you host — <strong>you implement</strong> these; you don't call them.</p>\n<ul>\n<li><strong>Catalogue / Push Asset</strong> — receives asset metadata whenever your catalogue changes in Snapplify.</li>\n<li><strong>Pay / Payment Completion</strong> — receives a payment token when a payment reaches a final state. You supply the URL per-payment via <code>notificationUrl</code> on Begin Payment.</li>\n</ul>\n<h2 id=\"support\">Support</h2>\n<p>Contact your Snapplify integration lead for credentials, webhook URL registration, partner-restricted endpoint access, or integration questions.</p>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"1306482","collectionId":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","publishedId":"2sAYBd88ZW","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"b9d13b"},"publishDate":"2026-04-18T10:39:49.000Z"},"item":[{"name":"Quickstart","item":[{"name":"1. Verify your API key","id":"19853e5e-d1b2-4bcc-9914-77a81324b95f","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/users?page=0&size=1","description":"<p><strong>Start here.</strong> This request confirms your API key and environment are configured correctly.</p>\n<p>Fill <code>api_key</code> in the <strong>Production</strong> environment, then click <strong>Send</strong>. A <code>200 OK</code> response (even with an empty user list) means your credentials work and you're ready to integrate.</p>\n<p>If you get <code>403 Forbidden</code>, check that the <code>api_key</code> environment variable is set and that you've selected the <strong>Production</strong> environment in the top-right dropdown.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["users"],"host":["https://api.snapplify.com"],"query":[{"key":"page","value":"0"},{"key":"size","value":"1"}],"variable":[]}},"response":[{"id":"854db95e-d68c-4e5d-bf08-909789d91052","name":"200 OK","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://api.snapplify.com/users?page=0&size=1","host":["https://api.snapplify.com"],"path":["users"],"query":[{"key":"page","value":"0"},{"key":"size","value":"1"}]},"description":"**Start here.** This request confirms your API key and environment are configured correctly.\n\nFill `api_key` in the **Production** environment, then click **Send**. A `200 OK` response (even with an empty user list) means your credentials work and you're ready to integrate.\n\nIf you get `403 Forbidden`, check that the `api_key` environment variable is set and that you've selected the **Production** environment in the top-right dropdown."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[]"},{"id":"207ff8de-86d2-47fb-8464-0fadf2025dd4","name":"403 Forbidden — wrong or missing api_key","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://api.snapplify.com/users?page=0&size=1","host":["https://api.snapplify.com"],"path":["users"],"query":[{"key":"page","value":"0"},{"key":"size","value":"1"}]},"description":"**Start here.** This request confirms your API key and environment are configured correctly.\n\nFill `api_key` in the **Production** environment, then click **Send**. A `200 OK` response (even with an empty user list) means your credentials work and you're ready to integrate.\n\nIf you get `403 Forbidden`, check that the `api_key` environment variable is set and that you've selected the **Production** environment in the top-right dropdown."},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"FORBIDDEN\",\n  \"message\": \"Bad credentials\"\n}"}],"_postman_id":"19853e5e-d1b2-4bcc-9914-77a81324b95f"},{"name":"2. Provision a test user","id":"f6be162e-43fa-4c58-8e35-5b0bae2b689f","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"externalId\": \"quickstart-demo-1\",\n  \"username\": \"quickstart.demo@example.com\",\n  \"firstname\": \"Demo\",\n  \"lastname\": \"Learner\",\n  \"email\": \"quickstart.demo@example.com\",\n  \"roles\": [\n    \"LEARNER\"\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/users","description":"<p>Create (or upsert) a user in your Snapplify tenant. The <code>externalId</code> is your stable identifier — sending the same <code>externalId</code> again updates the existing user rather than creating a duplicate.</p>\n<p>Save the returned <code>id</code> from the response — you'll use it in step 4.</p>\n<p>See <strong>Snapplify Access API</strong> for all supported fields (school, grade, auth providers for SSO, and so on).</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["users"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"f6be162e-43fa-4c58-8e35-5b0bae2b689f"},{"name":"3. Create a subscription plan","id":"49a52c8d-ae94-413b-bc69-0865a6785e36","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"type\": \"QuickstartPlan\",\n  \"identifiers\": [\n    \"9781234567890\"\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription","description":"<p>Create a subscription plan that bundles one or more assets (ISBNs / SKUs) under a named type.</p>\n<p>Save the returned <code>guid</code> — you'll use it in step 4 to grant the plan to your test user.</p>\n<p>See <strong>Snapplify Subscription API</strong> for the full concept (Subscription vs User Subscription) and all supported fields.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"49a52c8d-ae94-413b-bc69-0865a6785e36"},{"name":"4. Grant the subscription to your user","id":"122f6711-7d23-4b82-acf6-52050b7a1e03","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"userId\": 0,\n  \"subscriptionGuid\": \"paste-guid-from-step-3\",\n  \"status\": \"ACTIVE\",\n  \"expiresDate\": \"2026-12-31T00:00:00.000Z\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription/user","description":"<p>Link your test user to the subscription plan you just created.</p>\n<p>Before sending, update the body:</p>\n<ul>\n<li><code>userId</code> — the <code>id</code> returned from step 2</li>\n<li><code>subscriptionGuid</code> — the <code>guid</code> returned from step 3</li>\n</ul>\n<p>A <code>200 OK</code> response means the user now has entitlement to the assets listed in the plan. This is the full round trip: your code can now provision users and grant them access.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription","user"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"122f6711-7d23-4b82-acf6-52050b7a1e03"}],"id":"1bc6aa2a-f053-4362-88e3-41de1e646f3c","description":"<p><strong>A 5-minute end-to-end walkthrough.</strong> Run these four requests in order to confirm your integration is wired up correctly, from credentials to a full entitlement grant.</p>\n<h3 id=\"before-you-start\">Before you start</h3>\n<ol>\n<li>Select the <strong>Production</strong> environment in the top-right dropdown.</li>\n<li>Fill in <code>api_key</code> in the environment (you'll have received this during onboarding).</li>\n</ol>\n<h3 id=\"the-steps\">The steps</h3>\n<ol>\n<li><strong>Verify your API key</strong> — prove credentials work.</li>\n<li><strong>Provision a test user</strong> — creates a user in your Snapplify tenant.</li>\n<li><strong>Create a subscription plan</strong> — defines what the user gets access to.</li>\n<li><strong>Grant the subscription to your user</strong> — ties it together.</li>\n</ol>\n<p>Once you've completed this flow, you'll have the mental model for the rest of the collection. Head into the individual API folders below for the full reference.</p>\n<h3 id=\"other-common-integration-paths\">Other common integration paths</h3>\n<ul>\n<li><strong>Selling content</strong> — follow <strong>Snapplify Order API</strong> and <strong>Snapplify Pay</strong>.</li>\n<li><strong>Receiving catalogue updates</strong> — implement a webhook per <strong>Snapplify Catalogue API</strong>.</li>\n<li><strong>Browser-based SSO</strong> — see <strong>Snapplify Auth</strong> and use Postman's OAuth 2.0 helper on the User Info endpoint.</li>\n</ul>\n","_postman_id":"1bc6aa2a-f053-4362-88e3-41de1e646f3c","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}}},{"name":"Snapplify Auth","item":[{"name":"OAuth Authorize","id":"ff8ee961-e932-4cca-86e7-35699cfee053","request":{"method":"GET","header":[],"url":"https://auth.snapplify.com/oauth/authorize?response_type=code&client_id={{client_id}}&redirect_uri={{redirect_uri}}&scope=openid identity","description":"<p>Initiates the OAuth 2.0 / OIDC <strong>authorization code</strong> flow.</p>\n<p>This is a <strong>browser</strong> endpoint — open the URL in the user's user-agent. Snapplify will authenticate the user and then redirect to your <code>redirect_uri</code> with a <code>code</code> query parameter. Exchange that code for an access token using <strong>OAuth Token</strong>.</p>\n<h3 id=\"required-parameters\">Required parameters</h3>\n<ul>\n<li><code>response_type</code> — must be <code>code</code></li>\n<li><code>client_id</code> — your registered client ID</li>\n<li><code>redirect_uri</code> — must exactly match a registered redirect URI</li>\n<li><code>scope</code> — space-separated scopes (see below)</li>\n</ul>\n<h3 id=\"recommended\">Recommended</h3>\n<ul>\n<li><code>state</code> — opaque CSRF token; will be echoed back on redirect</li>\n</ul>\n<h2 id=\"supported-scopes\">Supported scopes</h2>\n<p>Scopes determine which fields are returned from the <strong>User Info</strong> endpoint. Some scopes are only available to partners on specific Access tiers.</p>\n<h3 id=\"access-basic-available-by-default\">Access Basic (available by default)</h3>\n<ul>\n<li><strong><code>openid</code></strong> — required for OIDC compliance; include in every request.</li>\n<li><strong><code>identity</code></strong> — grants access to the authenticated user's basic profile (id, email, name, authorities, mobileNumber, picture, emailVerified).</li>\n</ul>\n<h3 id=\"access-professional-or-enterprise\">Access Professional or Enterprise</h3>\n<ul>\n<li><strong><code>teacher</code></strong> — indicates the user is a teacher; adds <code>school</code>, <code>teacher</code>, and <code>teacher_verified</code> fields to the User Info response.</li>\n<li><strong><code>learner</code></strong> — indicates the user is a learner; adds <code>school</code>, <code>grade</code> (with nested <code>curriculum</code>), and <code>class[]</code> fields to the User Info response.</li>\n</ul>\n<p><strong>Scope combinations.</strong> Partners can request multiple scopes in a single authorization. For example, <code>openid identity teacher learner</code> grants access to all profile and role fields (subject to tier eligibility). Scopes not granted by the user's tier are silently ignored — your app will only receive fields for scopes actually granted.</p>\n<h3 id=\"errors\">Errors</h3>\n<p>Errors are returned via redirect to <code>redirect_uri</code> with <code>error</code> and <code>error_description</code> query parameters (per RFC 6749 §4.1.2.1).</p>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"ed22637a-6511-4854-8607-212e5bd14582","id":"ed22637a-6511-4854-8607-212e5bd14582","name":"Snapplify Auth","type":"folder"}},"urlObject":{"path":["oauth","authorize"],"host":["https://auth.snapplify.com"],"query":[{"description":{"content":"<p>Required. Must be <code>code</code> for the authorization code flow.</p>\n","type":"text/plain"},"key":"response_type","value":"code"},{"description":{"content":"<p>Required. The client ID issued to your application by Snapplify.</p>\n","type":"text/plain"},"key":"client_id","value":"{{client_id}}"},{"description":{"content":"<p>Required. Must exactly match a redirect URI registered for your client.</p>\n","type":"text/plain"},"key":"redirect_uri","value":"{{redirect_uri}}"},{"description":{"content":"<p>Space-separated scopes. <code>openid identity</code> is the standard sign-in baseline. Add <code>teacher</code> or <code>learner</code> to request expanded profile details in the User Info response. See the description below for the full scope reference and tier gating.</p>\n","type":"text/plain"},"key":"scope","value":"openid identity"},{"disabled":true,"description":{"content":"<p>Recommended. Opaque value returned to your redirect URI; use to prevent CSRF.</p>\n","type":"text/plain"},"key":"state","value":"<random_string>"},{"disabled":true,"description":{"content":"<p>Optional. Set to <code>login</code> to force re-authentication.</p>\n","type":"text/plain"},"key":"prompt","value":"login"},{"disabled":true,"description":{"content":"<p>Optional. Skip Snapplify login and route directly to a provider (<code>google</code>, <code>apple</code>, <code>microsoft</code>).</p>\n","type":"text/plain"},"key":"provider","value":"google"}],"variable":[]}},"response":[{"id":"e80aae0b-0939-42d6-9239-93cc065ae56f","name":"302 Redirect with code","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://auth.snapplify.com/oauth/authorize?response_type=code&client_id={{client_id}}&redirect_uri={{redirect_uri}}&scope=openid identity","host":["https://auth.snapplify.com"],"path":["oauth","authorize"],"query":[{"key":"response_type","value":"code","description":"Required. Must be `code` for the authorization code flow."},{"key":"client_id","value":"{{client_id}}","description":"Required. The client ID issued to your application by Snapplify."},{"key":"redirect_uri","value":"{{redirect_uri}}","description":"Required. Must exactly match a redirect URI registered for your client."},{"key":"scope","value":"openid identity","description":"Space-separated scopes. `openid` for OIDC; `identity` to access user profile via /userinfo."},{"key":"state","value":"<random_string>","description":"Recommended. Opaque value returned to your redirect URI; use to prevent CSRF.","disabled":true},{"key":"prompt","value":"login","description":"Optional. Set to `login` to force re-authentication.","disabled":true},{"key":"provider","value":"google","description":"Optional. Skip Snapplify login and route directly to a provider (`google`, `apple`, `microsoft`).","disabled":true}]},"description":"Initiates the OAuth 2.0 / OIDC **authorization code** flow.\n\nThis is a **browser** endpoint — open the URL in the user's user-agent. Snapplify will authenticate the user and then redirect to your `redirect_uri` with a `code` query parameter. Exchange that code for an access token using **OAuth Token**.\n\n### Required parameters\n- `response_type` — must be `code`\n- `client_id` — your registered client ID\n- `redirect_uri` — must exactly match a registered redirect URI\n- `scope` — space-separated scopes; use `openid identity` for standard sign-in\n\n### Recommended\n- `state` — opaque CSRF token; will be echoed back on redirect\n\n### Errors\nErrors are returned via redirect to `redirect_uri` with `error` and `error_description` query parameters (per RFC 6749 §4.1.2.1)."},"status":"Found","code":302,"_postman_previewlanguage":"text","header":[{"key":"Location","value":"{{redirect_uri}}?code=AQAAAS...&state=<state>"}],"cookie":[],"responseTime":null,"body":""}],"_postman_id":"ff8ee961-e932-4cca-86e7-35699cfee053"},{"name":"OAuth Token","id":"322a21ac-913c-4056-bf51-b14d263cdff7","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/x-www-form-urlencoded"}],"body":{"mode":"urlencoded","urlencoded":[{"key":"grant_type","value":"authorization_code","description":"<p>Required. Must be <code>authorization_code</code>.</p>\n"},{"key":"client_id","value":"{{client_id}}","description":"<p>Required.</p>\n"},{"key":"client_secret","value":"{{client_secret}}","description":"<p>Required. Keep server-side; never embed in clients.</p>\n"},{"key":"code","value":"<code>","description":"<p>Required. The <code>code</code> returned from the OAuth Authorize redirect.</p>\n"},{"key":"redirect_uri","value":"{{redirect_uri}}","description":"<p>Required. Must match the redirect URI used in the authorize step.</p>\n"}]},"url":"https://auth.snapplify.com/oauth/token","description":"<p>Exchange an authorization code for an <strong>access token</strong> (and optionally a refresh token and ID token).</p>\n<p>Send <code>application/x-www-form-urlencoded</code> body. Per RFC 6749 §4.1.3.</p>\n<p>Use <code>client_secret</code> only from a trusted server. For public clients (mobile/SPA), use PKCE.</p>\n<h3 id=\"response\">Response</h3>\n<p>JSON containing <code>access_token</code>, <code>token_type</code>, <code>expires_in</code>, and (when scopes include <code>openid</code> or the client is configured for refresh) <code>id_token</code> and <code>refresh_token</code>.</p>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"ed22637a-6511-4854-8607-212e5bd14582","id":"ed22637a-6511-4854-8607-212e5bd14582","name":"Snapplify Auth","type":"folder"}},"urlObject":{"path":["oauth","token"],"host":["https://auth.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"0f1ef656-070a-400f-869f-60c8445281e4","name":"200 OK","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/x-www-form-urlencoded"}],"body":{"mode":"urlencoded","urlencoded":[{"key":"grant_type","value":"authorization_code","description":"Required. Must be `authorization_code`."},{"key":"client_id","value":"{{client_id}}","description":"Required."},{"key":"client_secret","value":"{{client_secret}}","description":"Required. Keep server-side; never embed in clients."},{"key":"code","value":"<code>","description":"Required. The `code` returned from the OAuth Authorize redirect."},{"key":"redirect_uri","value":"{{redirect_uri}}","description":"Required. Must match the redirect URI used in the authorize step."}]},"url":"https://auth.snapplify.com/oauth/token","description":"Exchange an authorization code for an **access token** (and optionally a refresh token and ID token).\n\nSend `application/x-www-form-urlencoded` body. Per RFC 6749 §4.1.3.\n\nUse `client_secret` only from a trusted server. For public clients (mobile/SPA), use PKCE.\n\n### Response\nJSON containing `access_token`, `token_type`, `expires_in`, and (when scopes include `openid` or the client is configured for refresh) `id_token` and `refresh_token`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"access_token\": \"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ii4uLiJ9...\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": 3600,\n  \"refresh_token\": \"def50200a1...\",\n  \"id_token\": \"eyJhbGciOiJSUzI1NiIs...\",\n  \"scope\": \"openid identity\"\n}"},{"id":"68d5d084-9ec7-4890-8d15-73908e697d5a","name":"400 invalid_grant","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/x-www-form-urlencoded"}],"body":{"mode":"urlencoded","urlencoded":[{"key":"grant_type","value":"authorization_code","description":"Required. Must be `authorization_code`."},{"key":"client_id","value":"{{client_id}}","description":"Required."},{"key":"client_secret","value":"{{client_secret}}","description":"Required. Keep server-side; never embed in clients."},{"key":"code","value":"<code>","description":"Required. The `code` returned from the OAuth Authorize redirect."},{"key":"redirect_uri","value":"{{redirect_uri}}","description":"Required. Must match the redirect URI used in the authorize step."}]},"url":"https://auth.snapplify.com/oauth/token","description":"Exchange an authorization code for an **access token** (and optionally a refresh token and ID token).\n\nSend `application/x-www-form-urlencoded` body. Per RFC 6749 §4.1.3.\n\nUse `client_secret` only from a trusted server. For public clients (mobile/SPA), use PKCE.\n\n### Response\nJSON containing `access_token`, `token_type`, `expires_in`, and (when scopes include `openid` or the client is configured for refresh) `id_token` and `refresh_token`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": \"invalid_grant\",\n  \"error_description\": \"The authorization code has expired or has already been used.\"\n}"}],"_postman_id":"322a21ac-913c-4056-bf51-b14d263cdff7"},{"name":"OAuth Token (Refresh)","id":"95603c1b-326f-4b33-8055-1859cf2d528c","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/x-www-form-urlencoded"}],"body":{"mode":"urlencoded","urlencoded":[{"key":"grant_type","value":"refresh_token","description":"<p>Required. Must be <code>refresh_token</code>.</p>\n"},{"key":"client_id","value":"{{client_id}}","description":"<p>Required.</p>\n"},{"key":"client_secret","value":"{{client_secret}}","description":"<p>Required for confidential clients.</p>\n"},{"key":"refresh_token","value":"<refresh_token>","description":"<p>Required. The refresh token from a prior token response.</p>\n"}]},"url":"https://auth.snapplify.com/oauth/token","description":"<p>Exchange a refresh token for a new access token. Per RFC 6749 §6.</p>\n<p>Same endpoint as <strong>OAuth Token</strong>, distinguished by <code>grant_type=refresh_token</code>.</p>\n<p>If the refresh token is revoked or expired, the response is <code>400 invalid_grant</code> and the user must re-authenticate via <strong>OAuth Authorize</strong>.</p>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"ed22637a-6511-4854-8607-212e5bd14582","id":"ed22637a-6511-4854-8607-212e5bd14582","name":"Snapplify Auth","type":"folder"}},"urlObject":{"path":["oauth","token"],"host":["https://auth.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"d87a8985-e3aa-4821-b37e-2d250b8adc39","name":"200 OK","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/x-www-form-urlencoded"}],"body":{"mode":"urlencoded","urlencoded":[{"key":"grant_type","value":"refresh_token","description":"Required. Must be `refresh_token`."},{"key":"client_id","value":"{{client_id}}","description":"Required."},{"key":"client_secret","value":"{{client_secret}}","description":"Required for confidential clients."},{"key":"refresh_token","value":"<refresh_token>","description":"Required. The refresh token from a prior token response."}]},"url":"https://auth.snapplify.com/oauth/token","description":"Exchange a refresh token for a new access token. Per RFC 6749 §6.\n\nSame endpoint as **OAuth Token**, distinguished by `grant_type=refresh_token`.\n\nIf the refresh token is revoked or expired, the response is `400 invalid_grant` and the user must re-authenticate via **OAuth Authorize**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"access_token\": \"eyJhbGciOiJSUzI1NiIs...\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": 3600,\n  \"refresh_token\": \"def50200b2...\",\n  \"scope\": \"openid identity\"\n}"}],"_postman_id":"95603c1b-326f-4b33-8055-1859cf2d528c"},{"name":"OAuth JWKS","id":"0762e2a1-347b-4588-bd2a-24f8533efa0a","request":{"method":"GET","header":[],"url":"https://auth.snapplify.com/oauth/jwks","description":"<p>Public <strong>JSON Web Key Set</strong> for verifying signatures on Snapplify-issued JWTs (access tokens and ID tokens).</p>\n<p>Match the <code>kid</code> in the JWT header against an entry in <code>keys[]</code>. Cache the response and refresh periodically (the <code>kid</code> rotates; do not pin a single key).</p>\n<p>No authentication required.</p>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"ed22637a-6511-4854-8607-212e5bd14582","id":"ed22637a-6511-4854-8607-212e5bd14582","name":"Snapplify Auth","type":"folder"}},"urlObject":{"path":["oauth","jwks"],"host":["https://auth.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"97aad20d-2a62-4013-8619-aaad875ff330","name":"200 OK","originalRequest":{"method":"GET","header":[],"url":"https://auth.snapplify.com/oauth/jwks","description":"Public **JSON Web Key Set** for verifying signatures on Snapplify-issued JWTs (access tokens and ID tokens).\n\nMatch the `kid` in the JWT header against an entry in `keys[]`. Cache the response and refresh periodically (the `kid` rotates; do not pin a single key).\n\nNo authentication required."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"keys\": [\n    {\n      \"kty\": \"RSA\",\n      \"use\": \"sig\",\n      \"kid\": \"snapplify-2025\",\n      \"alg\": \"RS256\",\n      \"n\": \"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFb...\",\n      \"e\": \"AQAB\"\n    }\n  ]\n}"}],"_postman_id":"0762e2a1-347b-4588-bd2a-24f8533efa0a"},{"name":"User Info","id":"ba87727a-fd75-49e1-bc4d-71471d8e18cd","request":{"auth":{"type":"oauth2","oauth2":{"basicConfig":[],"advancedConfig":[{"key":"tokenName","value":"<token-name>"},{"key":"grant_type","value":"<grant_type>"},{"key":"authUrl","value":"<auth-url>"},{"key":"accessTokenUrl","value":"<access-token-url>"},{"key":"clientId","value":"{{client_id}}"},{"key":"clientSecret","value":"{{client_secret}}"},{"key":"redirect_uri","value":"{{redirect_uri}}"},{"key":"scope","value":"<scope>"},{"key":"client_authentication","value":"<client_authentication>"},{"key":"useBrowser","value":"<use-browser>"}]},"isInherited":false},"method":"GET","header":[],"url":"https://auth.snapplify.com/api/userinfo","description":"<p>Returns the authenticated user's profile.</p>\n<p><strong>Requires</strong> an access token obtained from <strong>OAuth Token</strong>.</p>\n<h3 id=\"response-fields-depend-on-requested-scopes\">Response fields depend on requested scopes</h3>\n<p>The fields in the response vary based on which scopes were granted during <strong>OAuth Authorize</strong>. Your app will only receive fields for scopes it was actually granted.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Scope</th>\n<th>Fields returned</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>identity</code></td>\n<td><code>id</code>, <code>email</code>, <code>name</code>, <code>given_name</code>, <code>family_name</code>, <code>username</code>, <code>picture</code>, <code>mobileNumber</code>, <code>email_verified</code> / <code>emailVerified</code>, <code>authorities</code></td>\n</tr>\n<tr>\n<td><code>teacher</code> (Professional/Enterprise)</td>\n<td>+ <code>school</code>, <code>teacher</code>, <code>teacher_verified</code></td>\n</tr>\n<tr>\n<td><code>learner</code> (Professional/Enterprise)</td>\n<td>+ <code>school</code>, <code>grade</code> (nested <code>curriculum</code>), <code>class[]</code></td>\n</tr>\n</tbody>\n</table>\n</div><p>The <code>authorities</code> array mixes OAuth scopes (<code>openid</code>, <code>identity</code>) and Snapplify roles (<code>learner</code>, <code>teacher</code>). <code>teacher_verified</code> indicates whether the teacher claim has been verified by Snapplify, distinct from merely being marked as a teacher.</p>\n<p>Some boolean fields are emitted in both <code>snake_case</code> and <code>camelCase</code> (e.g. <code>email_verified</code> / <code>emailVerified</code>) for backwards compatibility — prefer the snake_case form.</p>\n<h3 id=\"errors\">Errors</h3>\n<ul>\n<li><code>401 Unauthorized</code> — missing, expired, or revoked access token</li>\n<li><code>403 Forbidden</code> — token lacks the <code>identity</code> scope</li>\n</ul>\n","urlObject":{"path":["api","userinfo"],"host":["https://auth.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"c9611e0d-b455-40a0-aa91-0000073f7ce4","name":"200 OK — Learner","originalRequest":{"auth":{"type":"bearer","bearer":{"token":"<access_token>"}},"method":"GET","header":[{"key":"Authorization","value":"Bearer <access_token>","description":"Access token issued by **OAuth Token**. Requires the `identity` scope."}],"url":"https://auth.snapplify.com/api/userinfo","description":"Returns the authenticated user's profile, including their school, grade, curriculum, and class enrolments.\n\n**Requires** an access token with the `identity` scope (granted by including `identity` in the `scope` parameter on **OAuth Authorize**).\n\n### Key fields\n- `id` — stable Snapplify user identifier (integer)\n- `email`, `name`, `given_name`, `family_name` — standard profile fields\n- `authorities` — array mixing OAuth scopes (`openid`, `identity`) and Snapplify roles (`learner`, `teacher`)\n- `teacher` / `teacher_verified` — booleans; `teacher_verified` indicates the teacher claim has been verified by Snapplify\n- `school` — the user's school (id, name, vanity URL)\n- `grade` — the user's grade with nested `curriculum` (e.g. CAPS for South Africa)\n- `class` — array of class enrolments, each with its own `grade`\n\nSome boolean fields are emitted in both `snake_case` and `camelCase` (e.g. `email_verified` / `emailVerified`) for backwards compatibility — prefer the snake_case form.\n\n### Errors\n- `401 Unauthorized` — missing, expired, or revoked access token\n- `403 Forbidden` — token lacks the `identity` scope"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"id\": 1001,\n  \"email\": \"jane.doe@example.com\",\n  \"name\": \"Jane Doe\",\n  \"username\": \"jane.doe@example.com\",\n  \"given_name\": \"Jane\",\n  \"family_name\": \"Doe\",\n  \"picture\": \"https://cdn.snapplify.com/avatars/default.png\",\n  \"mobileNumber\": null,\n  \"email_verified\": true,\n  \"emailVerified\": true,\n  \"authorities\": [\n    \"learner\",\n    \"openid\",\n    \"identity\"\n  ],\n  \"school\": {\n    \"id\": 501,\n    \"name\": \"Example High School\",\n    \"url\": \"https://examplehighschool.snapplify.com/\",\n    \"createdDate\": \"2017-11-16 11:48:09\",\n    \"updatedDate\": \"2026-02-17 08:01:24\"\n  },\n  \"teacher\": false,\n  \"teacher_verified\": false,\n  \"grade\": {\n    \"id\": 11,\n    \"name\": \"Grade 10\",\n    \"createdDate\": \"2022-11-21 11:05:12\",\n    \"updatedDate\": \"2022-11-21 11:05:12\",\n    \"curriculum\": {\n      \"id\": 1,\n      \"name\": \"CAPS\",\n      \"description\": \"Curriculum and Assessment Policy Statement used in South Africa's education system\",\n      \"createdDate\": \"2022-11-21 11:05:12\",\n      \"updatedDate\": \"2022-11-21 11:05:12\"\n    }\n  },\n  \"class\": [\n    {\n      \"id\": 11377,\n      \"name\": \"Example Literature Class\",\n      \"createdDate\": \"2022-03-29 09:47:34\",\n      \"updatedDate\": \"2022-03-29 09:47:34\",\n      \"grade\": {\n        \"id\": 11,\n        \"name\": \"Grade 10\",\n        \"description\": \"Grade 10\",\n        \"createdDate\": \"2018-10-25 12:51:02\",\n        \"updatedDate\": \"2022-10-08 20:05:43\"\n      }\n    }\n  ]\n}"},{"id":"4684ebc8-853e-4773-89b4-3b6b7933089c","name":"200 OK — Teacher","originalRequest":{"auth":{"type":"bearer","bearer":{"token":"<access_token>"}},"method":"GET","header":[{"key":"Authorization","value":"Bearer <access_token>","description":"Access token issued by **OAuth Token**. Requires the `identity` scope."}],"url":"https://auth.snapplify.com/api/userinfo","description":"Returns the authenticated user's profile, including their school, grade, curriculum, and class enrolments.\n\n**Requires** an access token with the `identity` scope (granted by including `identity` in the `scope` parameter on **OAuth Authorize**).\n\n### Key fields\n- `id` — stable Snapplify user identifier (integer)\n- `email`, `name`, `given_name`, `family_name` — standard profile fields\n- `authorities` — array mixing OAuth scopes (`openid`, `identity`) and Snapplify roles (`learner`, `teacher`)\n- `teacher` / `teacher_verified` — booleans; `teacher_verified` indicates the teacher claim has been verified by Snapplify\n- `school` — the user's school (id, name, vanity URL)\n- `grade` — the user's grade with nested `curriculum` (e.g. CAPS for South Africa)\n- `class` — array of class enrolments, each with its own `grade`\n\nSome boolean fields are emitted in both `snake_case` and `camelCase` (e.g. `email_verified` / `emailVerified`) for backwards compatibility — prefer the snake_case form.\n\n### Errors\n- `401 Unauthorized` — missing, expired, or revoked access token\n- `403 Forbidden` — token lacks the `identity` scope"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"id\": 2042,\n  \"email\": \"alex.morgan@example.com\",\n  \"name\": \"Alex Morgan\",\n  \"username\": \"alex.morgan@example.com\",\n  \"given_name\": \"Alex\",\n  \"family_name\": \"Morgan\",\n  \"picture\": \"https://cdn.snapplify.com/avatars/default.png\",\n  \"mobileNumber\": \"+27821234567\",\n  \"email_verified\": true,\n  \"emailVerified\": true,\n  \"authorities\": [\n    \"teacher\",\n    \"openid\",\n    \"identity\"\n  ],\n  \"school\": {\n    \"id\": 501,\n    \"name\": \"Example High School\",\n    \"url\": \"https://examplehighschool.snapplify.com/\",\n    \"createdDate\": \"2017-11-16 11:48:09\",\n    \"updatedDate\": \"2026-02-17 08:01:24\"\n  },\n  \"teacher\": true,\n  \"teacher_verified\": true,\n  \"grade\": null,\n  \"class\": [\n    {\n      \"id\": 11377,\n      \"name\": \"Example Literature Class\",\n      \"createdDate\": \"2022-03-29 09:47:34\",\n      \"updatedDate\": \"2022-03-29 09:47:34\",\n      \"grade\": {\n        \"id\": 11,\n        \"name\": \"Grade 10\",\n        \"description\": \"Grade 10\",\n        \"createdDate\": \"2018-10-25 12:51:02\",\n        \"updatedDate\": \"2022-10-08 20:05:43\"\n      }\n    },\n    {\n      \"id\": 11842,\n      \"name\": \"Example Mathematics Class\",\n      \"createdDate\": \"2023-01-18 08:15:00\",\n      \"updatedDate\": \"2023-01-18 08:15:00\",\n      \"grade\": {\n        \"id\": 12,\n        \"name\": \"Grade 11\",\n        \"description\": \"Grade 11\",\n        \"createdDate\": \"2018-10-25 12:51:02\",\n        \"updatedDate\": \"2022-10-08 20:05:43\"\n      }\n    }\n  ]\n}"},{"id":"cb9b5bfa-c778-4ba7-83c6-a803973a4bc7","name":"401 Unauthorized","originalRequest":{"auth":{"type":"bearer","bearer":{"token":"<access_token>"}},"method":"GET","header":[{"key":"Authorization","value":"Bearer <access_token>","description":"Access token issued by **OAuth Token**. Requires the `identity` scope."}],"url":"https://auth.snapplify.com/api/userinfo","description":"Returns the authenticated user's profile, including their school, grade, curriculum, and class enrolments.\n\n**Requires** an access token with the `identity` scope (granted by including `identity` in the `scope` parameter on **OAuth Authorize**).\n\n### Key fields\n- `id` — stable Snapplify user identifier (integer)\n- `email`, `name`, `given_name`, `family_name` — standard profile fields\n- `authorities` — array mixing OAuth scopes (`openid`, `identity`) and Snapplify roles (`learner`, `teacher`)\n- `teacher` / `teacher_verified` — booleans; `teacher_verified` indicates the teacher claim has been verified by Snapplify\n- `school` — the user's school (id, name, vanity URL)\n- `grade` — the user's grade with nested `curriculum` (e.g. CAPS for South Africa)\n- `class` — array of class enrolments, each with its own `grade`\n\nSome boolean fields are emitted in both `snake_case` and `camelCase` (e.g. `email_verified` / `emailVerified`) for backwards compatibility — prefer the snake_case form.\n\n### Errors\n- `401 Unauthorized` — missing, expired, or revoked access token\n- `403 Forbidden` — token lacks the `identity` scope"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": \"invalid_token\",\n  \"error_description\": \"The access token expired\"\n}"}],"_postman_id":"ba87727a-fd75-49e1-bc4d-71471d8e18cd"},{"name":"OIDC Configuration","id":"f68a8b38-ede7-4390-ae3e-eaed4714f231","request":{"method":"GET","header":[],"url":"https://auth.snapplify.com/.well-known/openid-configuration","description":"<p>OpenID Connect Discovery 1.0 metadata document.</p>\n<p>Returns a JSON document advertising every endpoint URL (<code>authorization_endpoint</code>, <code>token_endpoint</code>, <code>userinfo_endpoint</code>, <code>end_session_endpoint</code>, <code>registration_endpoint</code>, <code>jwks_uri</code>, etc.), the supported scopes, grant types, response types, and signing algorithms.</p>\n<p>Use this to bootstrap an OIDC client library rather than hardcoding individual URLs — the document is the authoritative source for the auth server's capabilities.</p>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"ed22637a-6511-4854-8607-212e5bd14582","id":"ed22637a-6511-4854-8607-212e5bd14582","name":"Snapplify Auth","type":"folder"}},"urlObject":{"path":[".well-known","openid-configuration"],"host":["https://auth.snapplify.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"f68a8b38-ede7-4390-ae3e-eaed4714f231"},{"name":"Authorization Server Metadata","id":"ad5563c1-62ae-429f-86f1-6025aedf0529","request":{"method":"GET","header":[],"url":"https://auth.snapplify.com/.well-known/oauth-authorization-server","description":"<p>RFC 8414 OAuth 2.0 Authorization Server Metadata.</p>\n<p>Similar to the OIDC discovery document but scoped to plain OAuth 2.0 — use this if you are integrating OAuth 2.0 without OpenID Connect. OIDC clients should prefer <code>/.well-known/openid-configuration</code>.</p>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"ed22637a-6511-4854-8607-212e5bd14582","id":"ed22637a-6511-4854-8607-212e5bd14582","name":"Snapplify Auth","type":"folder"}},"urlObject":{"path":[".well-known","oauth-authorization-server"],"host":["https://auth.snapplify.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"ad5563c1-62ae-429f-86f1-6025aedf0529"},{"name":"Logout (RP-Initiated)","id":"9924e6a3-6c9c-49a1-a2ed-37309357eec7","request":{"method":"GET","header":[],"url":"https://auth.snapplify.com/connect/logout?id_token_hint={{id_token}}&client_id={{client_id}}&post_logout_redirect_uri=&state=","description":"<p>OpenID Connect RP-Initiated Logout 1.0 endpoint (<code>end_session_endpoint</code>).</p>\n<p>Terminates the End-User's session at the auth server and optionally redirects the browser back to a <code>post_logout_redirect_uri</code> registered for your client.</p>\n<p><strong>Typical flow:</strong></p>\n<ol>\n<li>Your app clears its local session.</li>\n<li>Your app redirects the browser to this endpoint, passing the <code>id_token_hint</code> (received on sign-in) and a registered <code>post_logout_redirect_uri</code>.</li>\n<li>The auth server terminates the session and redirects the browser back to your URI.</li>\n</ol>\n<p><strong>Caveats:</strong></p>\n<ul>\n<li><code>post_logout_redirect_uri</code> must be registered on your client. Contact Snapplify to register additional URIs.</li>\n<li>The next <code>/oauth/authorize</code> call for this client after a successful logout will show the login form instead of silently re-authenticating from a remembered session.</li>\n</ul>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"ed22637a-6511-4854-8607-212e5bd14582","id":"ed22637a-6511-4854-8607-212e5bd14582","name":"Snapplify Auth","type":"folder"}},"urlObject":{"path":["connect","logout"],"host":["https://auth.snapplify.com"],"query":[{"description":{"content":"<p>Recommended. The ID Token previously issued to this client during sign-in. Lets the auth server identify the client and session without an active browser session. Required in practice — without it the endpoint cannot resolve the session and will land the user on the generic signed-out page.</p>\n","type":"text/plain"},"key":"id_token_hint","value":"{{id_token}}"},{"description":{"content":"<p>Optional fallback when <code>id_token_hint</code> is not available.</p>\n","type":"text/plain"},"key":"client_id","value":"{{client_id}}"},{"description":{"content":"<p>Optional. URL to redirect the End-User to after logout. Must EXACTLY match a value registered for this client on the auth server — unregistered values are silently ignored.</p>\n","type":"text/plain"},"key":"post_logout_redirect_uri","value":""},{"description":{"content":"<p>Optional. Opaque value echoed back on the post-logout redirect; use for CSRF protection.</p>\n","type":"text/plain"},"key":"state","value":""}],"variable":[]}},"response":[],"_postman_id":"9924e6a3-6c9c-49a1-a2ed-37309357eec7"},{"name":"User Info (OIDC)","id":"836b57ad-2993-4710-a62b-22b0d26338cf","request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{access_token}}"}]},"isInherited":false},"method":"GET","header":[],"url":"https://auth.snapplify.com/userinfo","description":"<p>OpenID Connect-standard UserInfo endpoint.</p>\n<p>Returns claims about the authenticated End-User based on the scopes granted at authorization time — <code>openid identity</code> returns the subject and name claims, <code>profile</code> and <code>email</code> add the standard OIDC claims where available.</p>\n<p>Pass the <code>access_token</code> issued from <code>/oauth/token</code> as an HTTP Bearer credential.</p>\n","urlObject":{"path":["userinfo"],"host":["https://auth.snapplify.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"836b57ad-2993-4710-a62b-22b0d26338cf"},{"name":"Introspect Token","id":"1ca1697a-c571-4733-81d9-55556e4e0a36","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/x-www-form-urlencoded"}],"body":{"mode":"urlencoded","urlencoded":[{"key":"token","value":"<token>","description":"<p>Required. The access or refresh token to introspect.</p>\n"},{"key":"token_type_hint","value":"access_token","description":"<p>Optional. <code>access_token</code> or <code>refresh_token</code>.</p>\n"},{"key":"client_id","value":"{{client_id}}","description":"<p>Required.</p>\n"},{"key":"client_secret","value":"{{client_secret}}","description":"<p>Required. Keep server-side.</p>\n"}]},"url":"https://auth.snapplify.com/oauth/introspect","description":"<p>RFC 7662 OAuth 2.0 Token Introspection.</p>\n<p>Returns metadata about a given token — whether it is currently active, the client it was issued to, the scopes it was granted, the subject (user), and expiry.</p>\n<p>Use this when your resource server needs to validate opaque access tokens without having to decode and verify them directly. For JWTs you can usually verify locally against the JWKS — introspection is the authoritative source, but costs a round trip.</p>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"ed22637a-6511-4854-8607-212e5bd14582","id":"ed22637a-6511-4854-8607-212e5bd14582","name":"Snapplify Auth","type":"folder"}},"urlObject":{"path":["oauth","introspect"],"host":["https://auth.snapplify.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"1ca1697a-c571-4733-81d9-55556e4e0a36"},{"name":"Revoke Token","id":"24c04b99-f9e5-48a0-bcfb-4257340900a3","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/x-www-form-urlencoded"}],"body":{"mode":"urlencoded","urlencoded":[{"key":"token","value":"<token>","description":"<p>Required. The access or refresh token to revoke.</p>\n"},{"key":"token_type_hint","value":"access_token","description":"<p>Optional. <code>access_token</code> or <code>refresh_token</code>.</p>\n"},{"key":"client_id","value":"{{client_id}}","description":"<p>Required.</p>\n"},{"key":"client_secret","value":"{{client_secret}}","description":"<p>Required.</p>\n"}]},"url":"https://auth.snapplify.com/oauth/revoke","description":"<p>RFC 7009 OAuth 2.0 Token Revocation.</p>\n<p>Invalidates the given token immediately. Revoking a refresh token also revokes the associated access tokens.</p>\n<p>Call this when a user signs out of your app or when you detect token compromise. Note that for JWT access tokens cached by resource servers, revocation takes full effect only after the token expires naturally — verify against the introspection endpoint if you need immediate revocation enforcement.</p>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"ed22637a-6511-4854-8607-212e5bd14582","id":"ed22637a-6511-4854-8607-212e5bd14582","name":"Snapplify Auth","type":"folder"}},"urlObject":{"path":["oauth","revoke"],"host":["https://auth.snapplify.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"24c04b99-f9e5-48a0-bcfb-4257340900a3"},{"name":"Register Client (DCR)","id":"f75676c3-598b-4cba-a06e-03e87bca0373","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"client_name\": \"Example MCP Client\",\n  \"redirect_uris\": [\n    \"https://example.com/callback\"\n  ],\n  \"grant_types\": [\n    \"authorization_code\",\n    \"refresh_token\"\n  ],\n  \"response_types\": [\n    \"code\"\n  ],\n  \"token_endpoint_auth_method\": \"none\",\n  \"scope\": \"openid identity\"\n}","options":{"raw":{"language":"json"}}},"url":"https://auth.snapplify.com/oauth/register","description":"<p>RFC 7591 OAuth 2.0 Dynamic Client Registration.</p>\n<p>Self-service client registration for MCP integrations (Claude Desktop, VS Code, etc.) and other tooling that needs to obtain its own <code>client_id</code> without a manual provisioning step.</p>\n<p>Returns a newly-issued <code>client_id</code>. If <code>token_endpoint_auth_method</code> is anything other than <code>none</code>, a <code>client_secret</code> is also issued — store it securely server-side.</p>\n<p>For traditional partner integrations (web apps, mobile apps, server-to-server), please contact Snapplify to register a client manually rather than using DCR.</p>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"ed22637a-6511-4854-8607-212e5bd14582","id":"ed22637a-6511-4854-8607-212e5bd14582","name":"Snapplify Auth","type":"folder"}},"urlObject":{"path":["oauth","register"],"host":["https://auth.snapplify.com"],"query":[],"variable":[]}},"response":[],"_postman_id":"f75676c3-598b-4cba-a06e-03e87bca0373"}],"id":"ed22637a-6511-4854-8607-212e5bd14582","description":"<p>Snapplify uses <strong>OAuth 2.0 / OpenID Connect</strong> with the authorization code grant for partner integrations. Public clients (mobile, SPA) should use PKCE.</p>\n<p><strong>Flow:</strong> redirect the user to <strong>OAuth Authorize</strong> → receive <code>code</code> at your <code>redirect_uri</code> → exchange <code>code</code> at <strong>OAuth Token</strong> → call <strong>User Info</strong> with the resulting <code>access_token</code>.</p>\n<p>Use <strong>OAuth Token (Refresh)</strong> to renew access tokens without re-prompting the user, and <strong>OAuth JWKS</strong> to verify JWT signatures.</p>\n","auth":{"type":"noauth","isInherited":false},"_postman_id":"ed22637a-6511-4854-8607-212e5bd14582"},{"name":"Snapplify Access API","item":[{"name":"Upsert User","id":"b3949d81-e1d3-4de1-987e-5f0ad1511267","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"externalId\": \"partner-user-4421\",\n  \"username\": \"jane.doe@example.com\",\n  \"firstname\": \"Jane\",\n  \"lastname\": \"Doe\",\n  \"email\": \"jane.doe@example.com\",\n  \"mobileNumber\": \"+27821234567\",\n  \"schoolAttendanceType\": \"FULL_TIME\",\n  \"schoolStudentId\": \"STU-2024-004421\",\n  \"schoolClass\": \"10A\",\n  \"schoolName\": \"Example High School\",\n  \"schoolGrade\": \"Grade 10\",\n  \"grade\": {\n    \"name\": \"Grade 10\",\n    \"description\": \"Grade 10\"\n  },\n  \"roles\": [\n    \"LEARNER\"\n  ],\n  \"countryCode\": \"ZA\",\n  \"imageUrl\": \"https://cdn.example.com/avatars/jane.png\",\n  \"auth\": [\n    {\n      \"provider\": \"google\",\n      \"id\": \"112233445566778899001\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/users","description":"<p>Create or update a user, keyed on <code>externalId</code> (your identifier for the user).</p>\n<p>If a user already exists with the supplied <code>externalId</code> (within your customer scope), this request updates their record — including restoring a previously deleted user. Otherwise a new user is created. This makes the endpoint safe to call idempotently as part of your SSO / provisioning sync.</p>\n<p><code>PUT /users</code> is an alias for this endpoint with identical behaviour.</p>\n<h3 id=\"required-body-fields\">Required body fields</h3>\n<ul>\n<li><code>externalId</code> — your stable identifier for the user (used as the upsert key)</li>\n<li><code>username</code> — login username; typically the email</li>\n</ul>\n<h3 id=\"optional-body-fields\">Optional body fields</h3>\n<ul>\n<li><code>firstname</code>, <code>lastname</code>, <code>email</code>, <code>mobileNumber</code>, <code>imageUrl</code>, <code>countryCode</code></li>\n<li><code>roles[]</code> — any of <code>TEACHER</code>, <code>LEARNER</code>, <code>LIBRARIAN</code>, <code>ADMIN</code>, <code>CLASSROOM</code></li>\n<li><code>schoolAttendanceType</code>, <code>schoolStudentId</code>, <code>schoolClass</code>, <code>schoolName</code>, <code>schoolGrade</code></li>\n<li><code>grade</code> — <code>{ name, description }</code></li>\n<li><code>auth[]</code> — external identity providers; each <code>{ provider, id }</code>.   <code>provider</code> is one of <code>google</code>, <code>microsoft</code>, <code>snapplify</code>, <code>lti</code>.   <code>id</code> is the user's identifier at that provider. Use this to enable SSO sign-in for the user.</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["users"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"7da1174f-b9da-4c20-80a6-d6bf78e884db","name":"200 OK — Created","originalRequest":{"method":"POST","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"externalId\": \"partner-user-4421\",\n  \"username\": \"jane.doe@example.com\",\n  \"firstname\": \"Jane\",\n  \"lastname\": \"Doe\",\n  \"email\": \"jane.doe@example.com\",\n  \"mobileNumber\": \"+27821234567\",\n  \"schoolAttendanceType\": \"FULL_TIME\",\n  \"schoolStudentId\": \"STU-2024-004421\",\n  \"schoolClass\": \"10A\",\n  \"schoolName\": \"Example High School\",\n  \"schoolGrade\": \"Grade 10\",\n  \"grade\": {\n    \"name\": \"Grade 10\",\n    \"description\": \"Grade 10\"\n  },\n  \"roles\": [\n    \"LEARNER\"\n  ],\n  \"countryCode\": \"ZA\",\n  \"imageUrl\": \"https://cdn.example.com/avatars/jane.png\",\n  \"auth\": [\n    {\n      \"provider\": \"google\",\n      \"id\": \"112233445566778899001\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/users","description":"Create or update a user, keyed on `externalId` (your identifier for the user).\n\nIf a user already exists with the supplied `externalId` (within your customer scope), this request updates their record — including restoring a previously deleted user. Otherwise a new user is created. This makes the endpoint safe to call idempotently as part of your SSO / provisioning sync.\n\n`PUT /users` is an alias for this endpoint with identical behaviour.\n\n### Required body fields\n- `externalId` — your stable identifier for the user (used as the upsert key)\n- `username` — login username; typically the email\n\n### Optional body fields\n- `firstname`, `lastname`, `email`, `mobileNumber`, `imageUrl`, `countryCode`\n- `roles[]` — any of `TEACHER`, `LEARNER`, `LIBRARIAN`, `ADMIN`, `CLASSROOM`\n- `schoolAttendanceType`, `schoolStudentId`, `schoolClass`, `schoolName`, `schoolGrade`\n- `grade` — `{ name, description }`\n- `auth[]` — external identity providers; each `{ provider, id }`.   `provider` is one of `google`, `microsoft`, `snapplify`, `lti`.   `id` is the user's identifier at that provider. Use this to enable SSO sign-in for the user."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"id\": 2042,\n  \"archived\": false,\n  \"externalId\": \"partner-user-4421\",\n  \"uid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n  \"roles\": [\n    \"LEARNER\"\n  ],\n  \"schoolClasses\": [\n    {\n      \"id\": 11377,\n      \"name\": \"10A\"\n    }\n  ],\n  \"user\": {\n    \"id\": 3055,\n    \"username\": \"jane.doe@example.com\",\n    \"firstname\": \"Jane\",\n    \"lastname\": \"Doe\",\n    \"email\": \"jane.doe@example.com\",\n    \"imageUrl\": \"https://cdn.example.com/avatars/jane.png\",\n    \"mobileNumber\": \"+27821234567\",\n    \"schoolAttendanceType\": \"FULL_TIME\",\n    \"schoolStudentId\": \"STU-2024-004421\",\n    \"schoolClass\": \"10A\",\n    \"schoolGrade\": \"Grade 10\",\n    \"grade\": {\n      \"id\": 11,\n      \"name\": \"Grade 10\"\n    },\n    \"country\": {\n      \"code\": \"ZA\",\n      \"name\": \"South Africa\"\n    },\n    \"firstLogin\": \"2024-06-15T10:30:00.000Z\",\n    \"lastLogin\": \"2024-06-20T14:10:00.000Z\",\n    \"deleted\": false\n  },\n  \"auth\": [\n    {\n      \"id\": 99001,\n      \"authProvider\": \"google\",\n      \"authId\": \"112233445566778899001\"\n    }\n  ]\n}"},{"id":"51544cc3-de24-420b-b4df-db52ae2e6a82","name":"200 OK — Updated (existing externalId)","originalRequest":{"method":"POST","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"externalId\": \"partner-user-4421\",\n  \"username\": \"jane.doe@example.com\",\n  \"firstname\": \"Jane\",\n  \"lastname\": \"Doe\",\n  \"email\": \"jane.doe@example.com\",\n  \"mobileNumber\": \"+27821234567\",\n  \"schoolAttendanceType\": \"FULL_TIME\",\n  \"schoolStudentId\": \"STU-2024-004421\",\n  \"schoolClass\": \"10A\",\n  \"schoolName\": \"Example High School\",\n  \"schoolGrade\": \"Grade 10\",\n  \"grade\": {\n    \"name\": \"Grade 10\",\n    \"description\": \"Grade 10\"\n  },\n  \"roles\": [\n    \"LEARNER\"\n  ],\n  \"countryCode\": \"ZA\",\n  \"imageUrl\": \"https://cdn.example.com/avatars/jane.png\",\n  \"auth\": [\n    {\n      \"provider\": \"google\",\n      \"id\": \"112233445566778899001\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/users","description":"Create or update a user, keyed on `externalId` (your identifier for the user).\n\nIf a user already exists with the supplied `externalId` (within your customer scope), this request updates their record — including restoring a previously deleted user. Otherwise a new user is created. This makes the endpoint safe to call idempotently as part of your SSO / provisioning sync.\n\n`PUT /users` is an alias for this endpoint with identical behaviour.\n\n### Required body fields\n- `externalId` — your stable identifier for the user (used as the upsert key)\n- `username` — login username; typically the email\n\n### Optional body fields\n- `firstname`, `lastname`, `email`, `mobileNumber`, `imageUrl`, `countryCode`\n- `roles[]` — any of `TEACHER`, `LEARNER`, `LIBRARIAN`, `ADMIN`, `CLASSROOM`\n- `schoolAttendanceType`, `schoolStudentId`, `schoolClass`, `schoolName`, `schoolGrade`\n- `grade` — `{ name, description }`\n- `auth[]` — external identity providers; each `{ provider, id }`.   `provider` is one of `google`, `microsoft`, `snapplify`, `lti`.   `id` is the user's identifier at that provider. Use this to enable SSO sign-in for the user."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"id\": 2042,\n  \"archived\": false,\n  \"externalId\": \"partner-user-4421\",\n  \"uid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n  \"roles\": [\n    \"LEARNER\"\n  ],\n  \"schoolClasses\": [\n    {\n      \"id\": 11377,\n      \"name\": \"10A\"\n    }\n  ],\n  \"user\": {\n    \"id\": 3055,\n    \"username\": \"jane.doe@example.com\",\n    \"firstname\": \"Jane\",\n    \"lastname\": \"Doe\",\n    \"email\": \"jane.doe@example.com\",\n    \"imageUrl\": \"https://cdn.example.com/avatars/jane.png\",\n    \"mobileNumber\": \"+27821234567\",\n    \"schoolAttendanceType\": \"FULL_TIME\",\n    \"schoolStudentId\": \"STU-2024-004421\",\n    \"schoolClass\": \"10A\",\n    \"schoolGrade\": \"Grade 10\",\n    \"grade\": {\n      \"id\": 11,\n      \"name\": \"Grade 10\"\n    },\n    \"country\": {\n      \"code\": \"ZA\",\n      \"name\": \"South Africa\"\n    },\n    \"firstLogin\": \"2024-06-15T10:30:00.000Z\",\n    \"lastLogin\": \"2024-06-20T14:10:00.000Z\",\n    \"deleted\": false\n  },\n  \"auth\": [\n    {\n      \"id\": 99001,\n      \"authProvider\": \"google\",\n      \"authId\": \"112233445566778899001\"\n    }\n  ]\n}"},{"id":"b5ca54f7-e2cd-4327-8a8c-f1d0190ca8a9","name":"400 Bad Request","originalRequest":{"method":"POST","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"externalId\": \"partner-user-4421\",\n  \"username\": \"jane.doe@example.com\",\n  \"firstname\": \"Jane\",\n  \"lastname\": \"Doe\",\n  \"email\": \"jane.doe@example.com\",\n  \"mobileNumber\": \"+27821234567\",\n  \"schoolAttendanceType\": \"FULL_TIME\",\n  \"schoolStudentId\": \"STU-2024-004421\",\n  \"schoolClass\": \"10A\",\n  \"schoolName\": \"Example High School\",\n  \"schoolGrade\": \"Grade 10\",\n  \"grade\": {\n    \"name\": \"Grade 10\",\n    \"description\": \"Grade 10\"\n  },\n  \"roles\": [\n    \"LEARNER\"\n  ],\n  \"countryCode\": \"ZA\",\n  \"imageUrl\": \"https://cdn.example.com/avatars/jane.png\",\n  \"auth\": [\n    {\n      \"provider\": \"google\",\n      \"id\": \"112233445566778899001\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/users","description":"Create or update a user, keyed on `externalId` (your identifier for the user).\n\nIf a user already exists with the supplied `externalId` (within your customer scope), this request updates their record — including restoring a previously deleted user. Otherwise a new user is created. This makes the endpoint safe to call idempotently as part of your SSO / provisioning sync.\n\n`PUT /users` is an alias for this endpoint with identical behaviour.\n\n### Required body fields\n- `externalId` — your stable identifier for the user (used as the upsert key)\n- `username` — login username; typically the email\n\n### Optional body fields\n- `firstname`, `lastname`, `email`, `mobileNumber`, `imageUrl`, `countryCode`\n- `roles[]` — any of `TEACHER`, `LEARNER`, `LIBRARIAN`, `ADMIN`, `CLASSROOM`\n- `schoolAttendanceType`, `schoolStudentId`, `schoolClass`, `schoolName`, `schoolGrade`\n- `grade` — `{ name, description }`\n- `auth[]` — external identity providers; each `{ provider, id }`.   `provider` is one of `google`, `microsoft`, `snapplify`, `lti`.   `id` is the user's identifier at that provider. Use this to enable SSO sign-in for the user."},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"BAD_REQUEST\",\n  \"message\": \"username must not be blank\"\n}"}],"_postman_id":"b3949d81-e1d3-4de1-987e-5f0ad1511267"},{"name":"Get Users","id":"3991a536-8f4b-48c7-adf6-23c521a9742c","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/users?page=0&size=10","description":"<p>List users within your customer scope, paginated.</p>\n<p><code>size</code> is capped at <strong>100</strong> server-side; values above 100 are clamped.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["users"],"host":["https://api.snapplify.com"],"query":[{"description":{"content":"<p>Zero-indexed page number.</p>\n","type":"text/plain"},"key":"page","value":"0"},{"description":{"content":"<p>Page size (max 100).</p>\n","type":"text/plain"},"key":"size","value":"10"}],"variable":[]}},"response":[{"id":"288e01de-61ed-4cfa-a86e-77e846c7d95a","name":"200 OK","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/users?page=0&size=10","host":["https://api.snapplify.com"],"path":["users"],"query":[{"key":"page","value":"0","description":"Zero-indexed page number."},{"key":"size","value":"10","description":"Page size (max 100)."}]},"description":"List users within your customer scope, paginated.\n\n`size` is capped at **100** server-side; values above 100 are clamped."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n  {\n    \"id\": 2042,\n    \"archived\": false,\n    \"externalId\": \"partner-user-4421\",\n    \"uid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n    \"roles\": [\n      \"LEARNER\"\n    ],\n    \"schoolClasses\": [\n      {\n        \"id\": 11377,\n        \"name\": \"10A\"\n      }\n    ],\n    \"user\": {\n      \"id\": 3055,\n      \"username\": \"jane.doe@example.com\",\n      \"firstname\": \"Jane\",\n      \"lastname\": \"Doe\",\n      \"email\": \"jane.doe@example.com\",\n      \"imageUrl\": \"https://cdn.example.com/avatars/jane.png\",\n      \"mobileNumber\": \"+27821234567\",\n      \"schoolAttendanceType\": \"FULL_TIME\",\n      \"schoolStudentId\": \"STU-2024-004421\",\n      \"schoolClass\": \"10A\",\n      \"schoolGrade\": \"Grade 10\",\n      \"grade\": {\n        \"id\": 11,\n        \"name\": \"Grade 10\"\n      },\n      \"country\": {\n        \"code\": \"ZA\",\n        \"name\": \"South Africa\"\n      },\n      \"firstLogin\": \"2024-06-15T10:30:00.000Z\",\n      \"lastLogin\": \"2024-06-20T14:10:00.000Z\",\n      \"deleted\": false\n    },\n    \"auth\": [\n      {\n        \"id\": 99001,\n        \"authProvider\": \"google\",\n        \"authId\": \"112233445566778899001\"\n      }\n    ]\n  }\n]"}],"_postman_id":"3991a536-8f4b-48c7-adf6-23c521a9742c"},{"name":"Get User By Id","id":"cb003876-7742-4170-a796-c968b6ba4d38","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/users/:id","description":"<p>Retrieve a single user by their <strong>Snapplify</strong> user id (the integer <code>id</code> field returned by Upsert User). If you only have the <code>externalId</code>, use Get Users with a filter or re-upsert.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["users",":id"],"host":["https://api.snapplify.com"],"query":[],"variable":[{"type":"any","value":"2042","key":"id"}]}},"response":[{"id":"f2ba9404-83a7-4b44-bc47-53928f2e3187","name":"200 OK","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/users/:id","host":["https://api.snapplify.com"],"path":["users",":id"],"variable":[{"key":"id","value":"2042"}]},"description":"Retrieve a single user by their **Snapplify** user id (the integer `id` field returned by Upsert User). If you only have the `externalId`, use Get Users with a filter or re-upsert."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"id\": 2042,\n  \"archived\": false,\n  \"externalId\": \"partner-user-4421\",\n  \"uid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n  \"roles\": [\n    \"LEARNER\"\n  ],\n  \"schoolClasses\": [\n    {\n      \"id\": 11377,\n      \"name\": \"10A\"\n    }\n  ],\n  \"user\": {\n    \"id\": 3055,\n    \"username\": \"jane.doe@example.com\",\n    \"firstname\": \"Jane\",\n    \"lastname\": \"Doe\",\n    \"email\": \"jane.doe@example.com\",\n    \"imageUrl\": \"https://cdn.example.com/avatars/jane.png\",\n    \"mobileNumber\": \"+27821234567\",\n    \"schoolAttendanceType\": \"FULL_TIME\",\n    \"schoolStudentId\": \"STU-2024-004421\",\n    \"schoolClass\": \"10A\",\n    \"schoolGrade\": \"Grade 10\",\n    \"grade\": {\n      \"id\": 11,\n      \"name\": \"Grade 10\"\n    },\n    \"country\": {\n      \"code\": \"ZA\",\n      \"name\": \"South Africa\"\n    },\n    \"firstLogin\": \"2024-06-15T10:30:00.000Z\",\n    \"lastLogin\": \"2024-06-20T14:10:00.000Z\",\n    \"deleted\": false\n  },\n  \"auth\": [\n    {\n      \"id\": 99001,\n      \"authProvider\": \"google\",\n      \"authId\": \"112233445566778899001\"\n    }\n  ]\n}"},{"id":"be00e43f-7fe2-45f5-9b94-4074b3f00d4b","name":"404 Not Found","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/users/:id","host":["https://api.snapplify.com"],"path":["users",":id"],"variable":[{"key":"id","value":"2042"}]},"description":"Retrieve a single user by their **Snapplify** user id (the integer `id` field returned by Upsert User). If you only have the `externalId`, use Get Users with a filter or re-upsert."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"NOT_FOUND\",\n  \"message\": \"User not found\"\n}"}],"_postman_id":"cb003876-7742-4170-a796-c968b6ba4d38"},{"name":"Update User","id":"aa92e2a5-b3ba-460d-9e90-0cb6352e88c6","request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"firstname\": \"Jane\",\n  \"lastname\": \"Doe-Smith\",\n  \"email\": \"jane.doe-smith@example.com\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/users/:id","description":"<p>Update an existing user by their Snapplify user id.</p>\n<p>Differs from Upsert User in that: (1) the target is identified by path id rather than <code>externalId</code>, and (2) it will not create a new user if the id doesn't exist.</p>\n<p>Fields omitted from the request body are left unchanged.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["users",":id"],"host":["https://api.snapplify.com"],"query":[],"variable":[{"type":"any","value":"2042","key":"id"}]}},"response":[{"id":"2ce16208-7e56-420e-80d6-96928b2b3947","name":"200 OK","originalRequest":{"method":"PUT","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"firstname\": \"Jane\",\n  \"lastname\": \"Doe-Smith\",\n  \"email\": \"jane.doe-smith@example.com\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://api.snapplify.com/users/:id","host":["https://api.snapplify.com"],"path":["users",":id"],"variable":[{"key":"id","value":"2042"}]},"description":"Update an existing user by their Snapplify user id.\n\nDiffers from Upsert User in that: (1) the target is identified by path id rather than `externalId`, and (2) it will not create a new user if the id doesn't exist.\n\nFields omitted from the request body are left unchanged."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"id\": 2042,\n  \"archived\": false,\n  \"externalId\": \"partner-user-4421\",\n  \"uid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n  \"roles\": [\n    \"LEARNER\"\n  ],\n  \"schoolClasses\": [\n    {\n      \"id\": 11377,\n      \"name\": \"10A\"\n    }\n  ],\n  \"user\": {\n    \"id\": 3055,\n    \"username\": \"jane.doe@example.com\",\n    \"firstname\": \"Jane\",\n    \"lastname\": \"Doe-Smith\",\n    \"email\": \"jane.doe-smith@example.com\",\n    \"imageUrl\": \"https://cdn.example.com/avatars/jane.png\",\n    \"mobileNumber\": \"+27821234567\",\n    \"schoolAttendanceType\": \"FULL_TIME\",\n    \"schoolStudentId\": \"STU-2024-004421\",\n    \"schoolClass\": \"10A\",\n    \"schoolGrade\": \"Grade 10\",\n    \"grade\": {\n      \"id\": 11,\n      \"name\": \"Grade 10\"\n    },\n    \"country\": {\n      \"code\": \"ZA\",\n      \"name\": \"South Africa\"\n    },\n    \"firstLogin\": \"2024-06-15T10:30:00.000Z\",\n    \"lastLogin\": \"2024-06-20T14:10:00.000Z\",\n    \"deleted\": false\n  },\n  \"auth\": [\n    {\n      \"id\": 99001,\n      \"authProvider\": \"google\",\n      \"authId\": \"112233445566778899001\"\n    }\n  ]\n}"},{"id":"9a19e7bd-38af-4988-9e70-d6abe3733181","name":"404 Not Found","originalRequest":{"method":"PUT","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"firstname\": \"Jane\",\n  \"lastname\": \"Doe-Smith\",\n  \"email\": \"jane.doe-smith@example.com\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://api.snapplify.com/users/:id","host":["https://api.snapplify.com"],"path":["users",":id"],"variable":[{"key":"id","value":"2042"}]},"description":"Update an existing user by their Snapplify user id.\n\nDiffers from Upsert User in that: (1) the target is identified by path id rather than `externalId`, and (2) it will not create a new user if the id doesn't exist.\n\nFields omitted from the request body are left unchanged."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"NOT_FOUND\",\n  \"message\": \"User not found\"\n}"}],"_postman_id":"aa92e2a5-b3ba-460d-9e90-0cb6352e88c6"},{"name":"Delete User","id":"cf66fdcb-cf75-4219-b33e-e96b3e3c4f27","request":{"method":"DELETE","header":[],"url":"https://api.snapplify.com/users/:id","description":"<p>Soft-delete a single user by their Snapplify user id. The user's record is marked <code>deleted</code> rather than physically removed — you can restore them by upserting again with the same <code>externalId</code>.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["users",":id"],"host":["https://api.snapplify.com"],"query":[],"variable":[{"type":"any","value":"2042","key":"id"}]}},"response":[{"id":"05123c19-a081-4231-8e63-6a4d4915b85b","name":"200 OK","originalRequest":{"method":"DELETE","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/users/:id","host":["https://api.snapplify.com"],"path":["users",":id"],"variable":[{"key":"id","value":"2042"}]},"description":"Soft-delete a single user by their Snapplify user id. The user's record is marked `deleted` rather than physically removed — you can restore them by upserting again with the same `externalId`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"OK\",\n  \"message\": \"User deleted\"\n}"},{"id":"64c501b9-7d1e-47f5-a837-adb6792089f7","name":"404 Not Found","originalRequest":{"method":"DELETE","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/users/:id","host":["https://api.snapplify.com"],"path":["users",":id"],"variable":[{"key":"id","value":"2042"}]},"description":"Soft-delete a single user by their Snapplify user id. The user's record is marked `deleted` rather than physically removed — you can restore them by upserting again with the same `externalId`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"NOT_FOUND\",\n  \"message\": \"User not found\"\n}"}],"_postman_id":"cf66fdcb-cf75-4219-b33e-e96b3e3c4f27"},{"name":"Delete Users (Bulk)","id":"d8be4dea-0ec8-4f75-aa88-6a3854ff5b37","request":{"method":"DELETE","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"externalId\": \"partner-user-4421\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/users","description":"<p>Bulk-delete users by <code>externalId</code>. Unlike single-user delete, this operates on your identifier rather than the Snapplify id — useful when you want to deprovision users as part of your outbound sync without having to look up Snapplify ids first.</p>\n<p>Users are soft-deleted (same semantics as single-user delete).</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["users"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"31230498-409d-49d3-afea-72258558f4b4","name":"200 OK","originalRequest":{"method":"DELETE","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"externalId\": \"partner-user-4421\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/users","description":"Bulk-delete users by `externalId`. Unlike single-user delete, this operates on your identifier rather than the Snapplify id — useful when you want to deprovision users as part of your outbound sync without having to look up Snapplify ids first.\n\nUsers are soft-deleted (same semantics as single-user delete)."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"id\": 2042,\n  \"archived\": false,\n  \"externalId\": \"partner-user-4421\",\n  \"uid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n  \"roles\": [\n    \"LEARNER\"\n  ],\n  \"schoolClasses\": [\n    {\n      \"id\": 11377,\n      \"name\": \"10A\"\n    }\n  ],\n  \"user\": {\n    \"id\": 3055,\n    \"username\": \"jane.doe@example.com\",\n    \"firstname\": \"Jane\",\n    \"lastname\": \"Doe\",\n    \"email\": \"jane.doe@example.com\",\n    \"imageUrl\": \"https://cdn.example.com/avatars/jane.png\",\n    \"mobileNumber\": \"+27821234567\",\n    \"schoolAttendanceType\": \"FULL_TIME\",\n    \"schoolStudentId\": \"STU-2024-004421\",\n    \"schoolClass\": \"10A\",\n    \"schoolGrade\": \"Grade 10\",\n    \"grade\": {\n      \"id\": 11,\n      \"name\": \"Grade 10\"\n    },\n    \"country\": {\n      \"code\": \"ZA\",\n      \"name\": \"South Africa\"\n    },\n    \"firstLogin\": \"2024-06-15T10:30:00.000Z\",\n    \"lastLogin\": \"2024-06-20T14:10:00.000Z\",\n    \"deleted\": false\n  },\n  \"auth\": [\n    {\n      \"id\": 99001,\n      \"authProvider\": \"google\",\n      \"authId\": \"112233445566778899001\"\n    }\n  ]\n}"},{"id":"234d8d05-d6e0-40f6-8d2f-c9e069d67601","name":"404 Not Found","originalRequest":{"method":"DELETE","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"externalId\": \"partner-user-4421\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/users","description":"Bulk-delete users by `externalId`. Unlike single-user delete, this operates on your identifier rather than the Snapplify id — useful when you want to deprovision users as part of your outbound sync without having to look up Snapplify ids first.\n\nUsers are soft-deleted (same semantics as single-user delete)."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"NOT_FOUND\",\n  \"message\": \"User not found\"\n}"}],"_postman_id":"d8be4dea-0ec8-4f75-aa88-6a3854ff5b37"}],"id":"83c37671-2c77-4d0c-a206-c37aa27d92f0","description":"<p>The <strong>Snapplify Access API</strong> is a partner-facing <strong>user provisioning</strong> API. Use it to create, update, list, and delete users in a Snapplify customer tenant — typically as part of an SSO or directory sync from your system of record.</p>\n<h3 id=\"upsert-semantics-externalid\">Upsert semantics (externalId)</h3>\n<p>The primary pattern is to supply your own <code>externalId</code> on each user. Snapplify uses <code>externalId</code> as the idempotent key for <strong>Upsert User</strong> — resubmitting the same <code>externalId</code> updates the existing user (or restores them if they were previously deleted) rather than creating a duplicate. Your code doesn't need to track Snapplify user ids.</p>\n<h3 id=\"auth-providers\">Auth providers</h3>\n<p>Supply <code>auth[]</code> entries to wire up SSO: each entry is <code>{ provider, id }</code> where <code>provider</code> is one of <code>google</code>, <code>microsoft</code>, <code>snapplify</code>, or <code>lti</code>, and <code>id</code> is the user's identifier at that provider. Users can then sign in via that provider and land on the correct Snapplify account.</p>\n<h3 id=\"authentication\">Authentication</h3>\n<p>All endpoints require an API key in the <code>apiKey</code> header. All results are scoped to your customer automatically — you cannot see or modify users in other tenants.</p>\n<h3 id=\"pagination\">Pagination</h3>\n<p><code>Get Users</code> accepts <code>?page=N&amp;size=M</code>. <code>size</code> is capped at <strong>100</strong>.</p>\n","event":[{"listen":"prerequest","script":{"id":"be8df84b-63a1-412c-8695-b877ed1cb66e","type":"text/javascript","packages":{},"requests":{},"exec":[""]}},{"listen":"test","script":{"id":"46bef628-6365-44f9-bfc8-ede40545ab63","type":"text/javascript","packages":{},"requests":{},"exec":[""]}}],"_postman_id":"83c37671-2c77-4d0c-a206-c37aa27d92f0","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}}},{"name":"Snapplify Subscription API","item":[{"name":"Create Subscription","id":"43a77183-6063-4371-b805-94f7141da00e","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"type\": \"ProductSubscription\",\n  \"guid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n  \"identifiers\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription","description":"<p>Create a <strong>subscription</strong> — a plan template that bundles one or more assets (ISBNs/SKUs) into a named entitlement you can then grant to specific users via <strong>Create User Subscription</strong>.</p>\n<p>Subscriptions are owned by the caller; you can only see and modify subscriptions you created.</p>\n<h3 id=\"body-fields\">Body fields</h3>\n<ul>\n<li><code>type</code> — your subscription type/label (e.g. <code>ProductSubscription</code>)</li>\n<li><code>guid</code> — optional; if omitted, Snapplify generates one and returns it</li>\n<li><code>identifiers</code> — list of asset identifiers (ISBN/SKU) included in this subscription</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"8cf6c2b3-bb20-4197-a2b4-33b7787dca95","name":"200 OK","originalRequest":{"method":"POST","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"type\": \"ProductSubscription\",\n  \"guid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n  \"identifiers\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription","description":"Create a **subscription** — a plan template that bundles one or more assets (ISBNs/SKUs) into a named entitlement you can then grant to specific users via **Create User Subscription**.\n\nSubscriptions are owned by the caller; you can only see and modify subscriptions you created.\n\n### Body fields\n- `type` — your subscription type/label (e.g. `ProductSubscription`)\n- `guid` — optional; if omitted, Snapplify generates one and returns it\n- `identifiers` — list of asset identifiers (ISBN/SKU) included in this subscription"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"subscriptions\": [\n    {\n      \"guid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n      \"type\": \"ProductSubscription\",\n      \"identifiers\": [\n        \"9781234567890\",\n        \"9781234567906\"\n      ],\n      \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n      \"updatedDate\": \"2024-06-15T10:30:00.000Z\"\n    }\n  ]\n}"},{"id":"ed4aa672-232a-4405-b62d-392354370bd8","name":"400 Bad Request","originalRequest":{"method":"POST","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"type\": \"ProductSubscription\",\n  \"guid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n  \"identifiers\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription","description":"Create a **subscription** — a plan template that bundles one or more assets (ISBNs/SKUs) into a named entitlement you can then grant to specific users via **Create User Subscription**.\n\nSubscriptions are owned by the caller; you can only see and modify subscriptions you created.\n\n### Body fields\n- `type` — your subscription type/label (e.g. `ProductSubscription`)\n- `guid` — optional; if omitted, Snapplify generates one and returns it\n- `identifiers` — list of asset identifiers (ISBN/SKU) included in this subscription"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"BAD_REQUEST\",\n  \"message\": \"type must not be blank\"\n}"}],"_postman_id":"43a77183-6063-4371-b805-94f7141da00e"},{"name":"Get Subscription","id":"02508a0f-150b-45bf-ab7f-239320e7965e","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/subscription/:guid","description":"<p>Retrieve a single subscription by its <code>guid</code>. Returns the plan template with its asset identifiers.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription",":guid"],"host":["https://api.snapplify.com"],"query":[],"variable":[{"type":"any","value":"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f","key":"guid"}]}},"response":[{"id":"949ca9b8-1f17-46f1-978f-2596d470be0c","name":"200 OK","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/subscription/:guid","host":["https://api.snapplify.com"],"path":["subscription",":guid"],"variable":[{"key":"guid","value":"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f"}]},"description":"Retrieve a single subscription by its `guid`. Returns the plan template with its asset identifiers."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"subscriptions\": [\n    {\n      \"guid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n      \"type\": \"ProductSubscription\",\n      \"identifiers\": [\n        \"9781234567890\",\n        \"9781234567906\"\n      ],\n      \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n      \"updatedDate\": \"2024-06-15T10:30:00.000Z\"\n    }\n  ]\n}"},{"id":"41b6b189-664d-44ab-9950-5bfe05b8af6a","name":"404 Not Found","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/subscription/:guid","host":["https://api.snapplify.com"],"path":["subscription",":guid"],"variable":[{"key":"guid","value":"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f"}]},"description":"Retrieve a single subscription by its `guid`. Returns the plan template with its asset identifiers."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"NOT_FOUND\",\n  \"message\": \"Subscription not found\"\n}"}],"_postman_id":"02508a0f-150b-45bf-ab7f-239320e7965e"},{"name":"List Subscriptions","id":"81695797-c0ed-45d0-8e9b-b17e7e8b5a88","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/subscription?page=0&size=5","description":"<p>List subscriptions you have created, paginated. Only returns subscriptions owned by the caller.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription"],"host":["https://api.snapplify.com"],"query":[{"description":{"content":"<p>Zero-indexed page number.</p>\n","type":"text/plain"},"key":"page","value":"0"},{"description":{"content":"<p>Page size (server may cap).</p>\n","type":"text/plain"},"key":"size","value":"5"}],"variable":[]}},"response":[{"id":"ee01f400-e8e5-4003-9979-95339a138303","name":"200 OK","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/subscription?page=0&size=5","host":["https://api.snapplify.com"],"path":["subscription"],"query":[{"key":"page","value":"0","description":"Zero-indexed page number."},{"key":"size","value":"5","description":"Page size (server may cap)."}]},"description":"List subscriptions you have created, paginated. Only returns subscriptions owned by the caller."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"subscriptions\": [\n    {\n      \"guid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n      \"type\": \"ProductSubscription\",\n      \"identifiers\": [\n        \"9781234567890\",\n        \"9781234567906\"\n      ],\n      \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n      \"updatedDate\": \"2024-06-15T10:30:00.000Z\"\n    },\n    {\n      \"guid\": \"d9a2b3c4-5e6f-7a8b-9c0d-1e2f3a4b5c6e\",\n      \"type\": \"BookBundle\",\n      \"identifiers\": [\n        \"9781111111111\"\n      ],\n      \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n      \"updatedDate\": \"2024-06-15T10:30:00.000Z\"\n    }\n  ]\n}"}],"_postman_id":"81695797-c0ed-45d0-8e9b-b17e7e8b5a88"},{"name":"Update Subscription","id":"32e1c569-524f-451c-ab30-e1084af2f07a","request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"guid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n  \"type\": \"ProductSubscription\",\n  \"identifiers\": [\n    \"9781234567890\",\n    \"9781234567906\",\n    \"9781234567913\"\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription","description":"<p>Update an existing subscription. Identify the target by <code>guid</code> in the body. Fields omitted from the request are left unchanged.</p>\n<h3 id=\"body-fields\">Body fields</h3>\n<ul>\n<li><code>guid</code> — <strong>required</strong>; identifies the subscription to update</li>\n<li><code>type</code> — new type/label</li>\n<li><code>identifiers</code> — replaces the asset list (not merged)</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"be953e6c-1830-4baf-b723-01a918426e9a","name":"200 OK","originalRequest":{"method":"PUT","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"guid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n  \"type\": \"ProductSubscription\",\n  \"identifiers\": [\n    \"9781234567890\",\n    \"9781234567906\",\n    \"9781234567913\"\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription","description":"Update an existing subscription. Identify the target by `guid` in the body. Fields omitted from the request are left unchanged.\n\n### Body fields\n- `guid` — **required**; identifies the subscription to update\n- `type` — new type/label\n- `identifiers` — replaces the asset list (not merged)"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"subscriptions\": [\n    {\n      \"guid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n      \"type\": \"ProductSubscription\",\n      \"identifiers\": [\n        \"9781234567890\",\n        \"9781234567906\",\n        \"9781234567913\"\n      ],\n      \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n      \"updatedDate\": \"2024-06-20T14:10:00.000Z\"\n    }\n  ]\n}"},{"id":"085218d2-33f3-4390-be5a-fbe1a07c1076","name":"404 Not Found","originalRequest":{"method":"PUT","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"guid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n  \"type\": \"ProductSubscription\",\n  \"identifiers\": [\n    \"9781234567890\",\n    \"9781234567906\",\n    \"9781234567913\"\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription","description":"Update an existing subscription. Identify the target by `guid` in the body. Fields omitted from the request are left unchanged.\n\n### Body fields\n- `guid` — **required**; identifies the subscription to update\n- `type` — new type/label\n- `identifiers` — replaces the asset list (not merged)"},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"NOT_FOUND\",\n  \"message\": \"Subscription not found\"\n}"}],"_postman_id":"32e1c569-524f-451c-ab30-e1084af2f07a"},{"name":"Delete Subscription","id":"e7155123-da06-4fcc-a744-69ffd96f290c","request":{"method":"DELETE","header":[],"url":"https://api.snapplify.com/subscription/:guid","description":"<p>Delete a subscription plan template by <code>guid</code>. Only the creator can delete it.</p>\n<p>Deleting a subscription does not retroactively remove existing <strong>User Subscription</strong> grants — manage those separately via <strong>Delete User Subscription</strong>.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription",":guid"],"host":["https://api.snapplify.com"],"query":[],"variable":[{"type":"any","value":"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f","key":"guid"}]}},"response":[{"id":"4db53a87-4fde-4258-8f74-5326c07b079f","name":"200 OK","originalRequest":{"method":"DELETE","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/subscription/:guid","host":["https://api.snapplify.com"],"path":["subscription",":guid"],"variable":[{"key":"guid","value":"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f"}]},"description":"Delete a subscription plan template by `guid`. Only the creator can delete it.\n\nDeleting a subscription does not retroactively remove existing **User Subscription** grants — manage those separately via **Delete User Subscription**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":""},{"id":"a9b42b24-acd3-4208-aa27-e54dbd3eea86","name":"404 Not Found","originalRequest":{"method":"DELETE","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/subscription/:guid","host":["https://api.snapplify.com"],"path":["subscription",":guid"],"variable":[{"key":"guid","value":"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f"}]},"description":"Delete a subscription plan template by `guid`. Only the creator can delete it.\n\nDeleting a subscription does not retroactively remove existing **User Subscription** grants — manage those separately via **Delete User Subscription**."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"NOT_FOUND\",\n  \"message\": \"Subscription not found\"\n}"}],"_postman_id":"e7155123-da06-4fcc-a744-69ffd96f290c"},{"name":"Create User Subscription","id":"2dd6ffac-93f4-4bee-b453-817734371631","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"userId\": 1001,\n  \"subscriptionGuid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n  \"status\": \"ACTIVE\",\n  \"expiresDate\": \"2025-06-15T00:00:00.000Z\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription/user","description":"<p>Grant a subscription to a specific user. Creates a <strong>User Subscription</strong> record linking the user to one of your subscription plans.</p>\n<h3 id=\"body-fields\">Body fields</h3>\n<ul>\n<li><code>userId</code> — Snapplify user id to grant the subscription to</li>\n<li><code>subscriptionGuid</code> — the plan's <code>guid</code> (from Create/List Subscription)</li>\n<li><code>status</code> — one of <code>ACTIVE</code>, <code>EXPIRED</code>, <code>INACTIVE</code></li>\n<li><code>expiresDate</code> — ISO-8601 timestamp after which the grant is no longer valid</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription","user"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"e63a0e91-1a4f-4db0-bd6c-86092afde721","name":"200 OK","originalRequest":{"method":"POST","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"userId\": 1001,\n  \"subscriptionGuid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n  \"status\": \"ACTIVE\",\n  \"expiresDate\": \"2025-06-15T00:00:00.000Z\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription/user","description":"Grant a subscription to a specific user. Creates a **User Subscription** record linking the user to one of your subscription plans.\n\n### Body fields\n- `userId` — Snapplify user id to grant the subscription to\n- `subscriptionGuid` — the plan's `guid` (from Create/List Subscription)\n- `status` — one of `ACTIVE`, `EXPIRED`, `INACTIVE`\n- `expiresDate` — ISO-8601 timestamp after which the grant is no longer valid"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"user_subscriptions\": [\n    {\n      \"guid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n      \"userId\": 1001,\n      \"subscriptionGuid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n      \"status\": \"ACTIVE\",\n      \"expiresDate\": \"2025-06-15T00:00:00.000Z\",\n      \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n      \"updatedDate\": \"2024-06-15T10:30:00.000Z\"\n    }\n  ]\n}"},{"id":"1be67b94-aafa-4bd7-8031-f31ac5979f38","name":"400 Bad Request","originalRequest":{"method":"POST","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"userId\": 1001,\n  \"subscriptionGuid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n  \"status\": \"ACTIVE\",\n  \"expiresDate\": \"2025-06-15T00:00:00.000Z\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription/user","description":"Grant a subscription to a specific user. Creates a **User Subscription** record linking the user to one of your subscription plans.\n\n### Body fields\n- `userId` — Snapplify user id to grant the subscription to\n- `subscriptionGuid` — the plan's `guid` (from Create/List Subscription)\n- `status` — one of `ACTIVE`, `EXPIRED`, `INACTIVE`\n- `expiresDate` — ISO-8601 timestamp after which the grant is no longer valid"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"BAD_REQUEST\",\n  \"message\": \"subscriptionGuid not found\"\n}"}],"_postman_id":"2dd6ffac-93f4-4bee-b453-817734371631"},{"name":"Get User Subscription","id":"d1c293f3-eccd-455c-be62-863e24bd13d3","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/subscription/user/:guid","description":"<p>Retrieve a single user subscription grant by its <code>guid</code>.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription","user",":guid"],"host":["https://api.snapplify.com"],"query":[],"variable":[{"type":"any","value":"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d","key":"guid"}]}},"response":[{"id":"d38ea2af-6bef-407f-9520-48c0e777fcab","name":"200 OK","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/subscription/user/:guid","host":["https://api.snapplify.com"],"path":["subscription","user",":guid"],"variable":[{"key":"guid","value":"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d"}]},"description":"Retrieve a single user subscription grant by its `guid`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"user_subscriptions\": [\n    {\n      \"guid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n      \"userId\": 1001,\n      \"subscriptionGuid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n      \"status\": \"ACTIVE\",\n      \"expiresDate\": \"2025-06-15T00:00:00.000Z\",\n      \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n      \"updatedDate\": \"2024-06-15T10:30:00.000Z\"\n    }\n  ]\n}"},{"id":"b653f9af-fbee-41c2-b062-b68b2260295c","name":"404 Not Found","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/subscription/user/:guid","host":["https://api.snapplify.com"],"path":["subscription","user",":guid"],"variable":[{"key":"guid","value":"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d"}]},"description":"Retrieve a single user subscription grant by its `guid`."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"NOT_FOUND\",\n  \"message\": \"User subscription not found\"\n}"}],"_postman_id":"d1c293f3-eccd-455c-be62-863e24bd13d3"},{"name":"List User Subscriptions","id":"abd7a484-3b26-4a4a-941b-cb9f1c8482dc","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/subscription/user?page=0&size=5","description":"<p>List all user-subscription grants across all your subscription plans, paginated. Visibility is scoped by ownership of the underlying subscription.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription","user"],"host":["https://api.snapplify.com"],"query":[{"description":{"content":"<p>Zero-indexed page number.</p>\n","type":"text/plain"},"key":"page","value":"0"},{"description":{"content":"<p>Page size.</p>\n","type":"text/plain"},"key":"size","value":"5"}],"variable":[]}},"response":[{"id":"c57b00a5-68d1-45bf-b092-ec78fb4d3746","name":"200 OK","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/subscription/user?page=0&size=5","host":["https://api.snapplify.com"],"path":["subscription","user"],"query":[{"key":"page","value":"0","description":"Zero-indexed page number."},{"key":"size","value":"5","description":"Page size."}]},"description":"List all user-subscription grants across all your subscription plans, paginated. Visibility is scoped by ownership of the underlying subscription."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"user_subscriptions\": [\n    {\n      \"guid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n      \"userId\": 1001,\n      \"subscriptionGuid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n      \"status\": \"ACTIVE\",\n      \"expiresDate\": \"2025-06-15T00:00:00.000Z\",\n      \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n      \"updatedDate\": \"2024-06-15T10:30:00.000Z\"\n    },\n    {\n      \"guid\": \"b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e\",\n      \"userId\": 1002,\n      \"subscriptionGuid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n      \"status\": \"EXPIRED\",\n      \"expiresDate\": \"2024-01-01T00:00:00.000Z\",\n      \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n      \"updatedDate\": \"2024-06-15T10:30:00.000Z\"\n    }\n  ]\n}"}],"_postman_id":"abd7a484-3b26-4a4a-941b-cb9f1c8482dc"},{"name":"List One User's Subscriptions","id":"5cfb2c2b-56f7-4c7d-aa4d-51dc441e9d85","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/subscription/user/:userId/list?page=0&size=5","description":"<p>List subscription grants for a specific user. Use when you need to see everything granted to a single user.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription","user",":userId","list"],"host":["https://api.snapplify.com"],"query":[{"key":"page","value":"0"},{"key":"size","value":"5"}],"variable":[{"type":"any","value":"1001","key":"userId"}]}},"response":[{"id":"0694e161-ff40-4770-b008-d9cee409de8c","name":"200 OK","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/subscription/user/:userId/list?page=0&size=5","host":["https://api.snapplify.com"],"path":["subscription","user",":userId","list"],"query":[{"key":"page","value":"0"},{"key":"size","value":"5"}],"variable":[{"key":"userId","value":"1001"}]},"description":"List subscription grants for a specific user. Use when you need to see everything granted to a single user."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"user_subscriptions\": [\n    {\n      \"guid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n      \"userId\": 1001,\n      \"subscriptionGuid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n      \"status\": \"ACTIVE\",\n      \"expiresDate\": \"2025-06-15T00:00:00.000Z\",\n      \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n      \"updatedDate\": \"2024-06-15T10:30:00.000Z\"\n    }\n  ]\n}"}],"_postman_id":"5cfb2c2b-56f7-4c7d-aa4d-51dc441e9d85"},{"name":"Update User Subscription","id":"826c97be-6a44-46c4-825c-5d765a36c3c7","request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"guid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n  \"status\": \"INACTIVE\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription/user","description":"<p>Update a user-subscription grant — typically to change <code>status</code> or <code>expiresDate</code>. Identify by <code>guid</code> in the body.</p>\n<h3 id=\"status-transitions\">Status transitions</h3>\n<p><code>ACTIVE</code> → <code>INACTIVE</code> revokes access. <code>ACTIVE</code> → <code>EXPIRED</code> marks as ended but preserves the history. <code>INACTIVE</code> → <code>ACTIVE</code> restores access.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription","user"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"7f53726a-7006-4113-a000-185cad8b0e1c","name":"200 OK","originalRequest":{"method":"PUT","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"guid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n  \"status\": \"INACTIVE\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/subscription/user","description":"Update a user-subscription grant — typically to change `status` or `expiresDate`. Identify by `guid` in the body.\n\n### Status transitions\n`ACTIVE` → `INACTIVE` revokes access. `ACTIVE` → `EXPIRED` marks as ended but preserves the history. `INACTIVE` → `ACTIVE` restores access."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"user_subscriptions\": [\n    {\n      \"guid\": \"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n      \"userId\": 1001,\n      \"subscriptionGuid\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n      \"status\": \"INACTIVE\",\n      \"expiresDate\": \"2025-06-15T00:00:00.000Z\",\n      \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n      \"updatedDate\": \"2024-06-20T14:10:00.000Z\"\n    }\n  ]\n}"}],"_postman_id":"826c97be-6a44-46c4-825c-5d765a36c3c7"},{"name":"Delete User Subscription","id":"5605a06c-531a-4467-b42d-7bd541989002","request":{"method":"DELETE","header":[],"url":"https://api.snapplify.com/subscription/user/:guid","description":"<p>Delete a user-subscription grant by <code>guid</code>. Prefer <strong>Update User Subscription</strong> with <code>status: INACTIVE</code> when you want to revoke access but keep the audit record.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["subscription","user",":guid"],"host":["https://api.snapplify.com"],"query":[],"variable":[{"type":"any","value":"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d","key":"guid"}]}},"response":[{"id":"740e31aa-c3f7-41ce-82d3-84c506521f3a","name":"200 OK","originalRequest":{"method":"DELETE","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/subscription/user/:guid","host":["https://api.snapplify.com"],"path":["subscription","user",":guid"],"variable":[{"key":"guid","value":"a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d"}]},"description":"Delete a user-subscription grant by `guid`. Prefer **Update User Subscription** with `status: INACTIVE` when you want to revoke access but keep the audit record."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":""}],"_postman_id":"5605a06c-531a-4467-b42d-7bd541989002"}],"id":"bbef0340-0efb-4da7-ad10-37b4dbebfc17","description":"<p>The <strong>Snapplify Subscription API</strong> manages two concepts:</p>\n<ul>\n<li><strong>Subscription</strong> — a plan template you define, bundling one or more assets (ISBNs/SKUs) under   a named type. Analogous to a 'product definition'. Owned by the caller.</li>\n<li><strong>User Subscription</strong> — a grant of a subscription to a specific user, with a <code>status</code>   (<code>ACTIVE</code> / <code>EXPIRED</code> / <code>INACTIVE</code>) and optional <code>expiresDate</code>.</li>\n</ul>\n<p>Typical flow: <code>Create Subscription</code> once per plan, then <code>Create User Subscription</code> per user you want to grant access to. Revoke by updating to <code>INACTIVE</code> or deleting.</p>\n<h3 id=\"authentication\">Authentication</h3>\n<p>All endpoints require an API key in the <code>apiKey</code> header. Subscriptions and user-subscription grants are automatically scoped to the caller — you cannot see or modify subscriptions owned by other accounts. (Legacy headers <code>Token</code>, <code>AuthToken</code>, <code>authToken</code> are also accepted.)</p>\n<h3 id=\"response-shape\">Response shape</h3>\n<p>Responses are wrapped in <code>{\"subscriptions\": [...]}</code> or <code>{\"user_subscriptions\": [...]}</code>. Even single-item responses use the array form.</p>\n<h3 id=\"pagination\">Pagination</h3>\n<p><code>List</code> endpoints accept <code>?page=N&amp;size=M</code>. Page size is capped server-side.</p>\n","_postman_id":"bbef0340-0efb-4da7-ad10-37b4dbebfc17","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}}},{"name":"Snapplify Voucher API","item":[{"name":"Create Voucher","id":"4c0cc6aa-1b99-456b-acbf-688450ed8b4f","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"code\": \"SNAP-EXMPL-2024-A1B2\",\n  \"reference\": \"EXP-REF-00001\",\n  \"label\": \"Grade 10 Starter Pack\",\n  \"quantity\": 1,\n  \"recipientEmail\": \"student@example.com\",\n  \"assetIds\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ],\n  \"redeem\": false,\n  \"user\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/vouchers","description":"<p>Create a voucher that entitles the recipient to one or more assets (ISBNs/SKUs).</p>\n<p>Vouchers are scoped to the store associated with your API key. Once created, a voucher can be redeemed by the recipient via Snapplify's redemption flows; each redemption consumes one unit of <code>quantity</code>.</p>\n<h3 id=\"body-fields\">Body fields</h3>\n<ul>\n<li><code>code</code> — the voucher code the recipient will redeem. If omitted, Snapplify generates one.</li>\n<li><code>reference</code> — your reference for this voucher (for reconciliation on your side)</li>\n<li><code>label</code> — display label shown to the recipient</li>\n<li><code>quantity</code> — how many times the voucher can be redeemed (default <code>1</code>)</li>\n<li><code>recipientEmail</code> — optional. If supplied, Snapplify will email the voucher to this address.</li>\n<li><code>assetIds</code> — list of asset identifiers (ISBN/SKU) the voucher grants access to</li>\n<li><code>redeem</code> — if <code>true</code>, auto-redeems the voucher immediately against <code>user</code>. Requires <code>user</code>.</li>\n<li><code>user</code> — Snapplify user id to auto-redeem against (required if <code>redeem=true</code>)</li>\n</ul>\n<h3 id=\"errors\">Errors</h3>\n<ul>\n<li><code>400 Bad Request</code> — validation error (missing required field, invalid assetIds, duplicate code)</li>\n<li><code>403 Forbidden</code> — API key missing or invalid</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["vouchers"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"e39e94e0-b54b-4ce3-9eb7-aa0fce769f3f","name":"201 Created","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"body":{"mode":"raw","raw":"{\n  \"code\": \"SNAP-EXMPL-2024-A1B2\",\n  \"reference\": \"EXP-REF-00001\",\n  \"label\": \"Grade 10 Starter Pack\",\n  \"quantity\": 1,\n  \"recipientEmail\": \"student@example.com\",\n  \"assetIds\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ],\n  \"redeem\": false,\n  \"user\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/vouchers","description":"Create a voucher that entitles the recipient to one or more assets (ISBNs/SKUs).\n\nVouchers are scoped to the store associated with your API key. Once created, a voucher can be redeemed by the recipient via Snapplify's redemption flows; each redemption consumes one unit of `quantity`.\n\n### Body fields\n- `code` — the voucher code the recipient will redeem. If omitted, Snapplify generates one.\n- `reference` — your reference for this voucher (for reconciliation on your side)\n- `label` — display label shown to the recipient\n- `quantity` — how many times the voucher can be redeemed (default `1`)\n- `recipientEmail` — optional. If supplied, Snapplify will email the voucher to this address.\n- `assetIds` — list of asset identifiers (ISBN/SKU) the voucher grants access to\n- `redeem` — if `true`, auto-redeems the voucher immediately against `user`. Requires `user`.\n- `user` — Snapplify user id to auto-redeem against (required if `redeem=true`)\n\n### Errors\n- `400 Bad Request` — validation error (missing required field, invalid assetIds, duplicate code)\n- `403 Forbidden` — API key missing or invalid"},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"label\": \"Grade 10 Starter Pack\",\n  \"code\": \"SNAP-EXMPL-2024-A1B2\",\n  \"reference\": \"EXP-REF-00001\",\n  \"quantity\": 1,\n  \"quantityRemaining\": 1,\n  \"recipientEmail\": \"student@example.com\",\n  \"assetIds\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ],\n  \"activatedDate\": null,\n  \"createdDate\": \"2024-06-15T10:30:00.000Z\"\n}"},{"id":"e360bc4e-cf27-451b-8d21-8992c4d3a1b3","name":"201 Created — Auto-redeemed","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"body":{"mode":"raw","raw":"{\n  \"code\": \"SNAP-EXMPL-2024-A1B2\",\n  \"reference\": \"EXP-REF-00001\",\n  \"label\": \"Grade 10 Starter Pack\",\n  \"quantity\": 1,\n  \"recipientEmail\": \"student@example.com\",\n  \"assetIds\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ],\n  \"redeem\": false,\n  \"user\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/vouchers","description":"Create a voucher that entitles the recipient to one or more assets (ISBNs/SKUs).\n\nVouchers are scoped to the store associated with your API key. Once created, a voucher can be redeemed by the recipient via Snapplify's redemption flows; each redemption consumes one unit of `quantity`.\n\n### Body fields\n- `code` — the voucher code the recipient will redeem. If omitted, Snapplify generates one.\n- `reference` — your reference for this voucher (for reconciliation on your side)\n- `label` — display label shown to the recipient\n- `quantity` — how many times the voucher can be redeemed (default `1`)\n- `recipientEmail` — optional. If supplied, Snapplify will email the voucher to this address.\n- `assetIds` — list of asset identifiers (ISBN/SKU) the voucher grants access to\n- `redeem` — if `true`, auto-redeems the voucher immediately against `user`. Requires `user`.\n- `user` — Snapplify user id to auto-redeem against (required if `redeem=true`)\n\n### Errors\n- `400 Bad Request` — validation error (missing required field, invalid assetIds, duplicate code)\n- `403 Forbidden` — API key missing or invalid"},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"label\": \"Grade 10 Starter Pack\",\n  \"code\": \"SNAP-EXMPL-2024-A1B2\",\n  \"reference\": \"EXP-REF-00001\",\n  \"quantity\": 1,\n  \"quantityRemaining\": 0,\n  \"recipientEmail\": \"student@example.com\",\n  \"assetIds\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ],\n  \"activatedDate\": \"2024-06-15T10:30:15.000Z\",\n  \"createdDate\": \"2024-06-15T10:30:00.000Z\"\n}"},{"id":"abb08b3a-8745-42b4-a299-93b4dfb62ef0","name":"400 Bad Request","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"body":{"mode":"raw","raw":"{\n  \"code\": \"SNAP-EXMPL-2024-A1B2\",\n  \"reference\": \"EXP-REF-00001\",\n  \"label\": \"Grade 10 Starter Pack\",\n  \"quantity\": 1,\n  \"recipientEmail\": \"student@example.com\",\n  \"assetIds\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ],\n  \"redeem\": false,\n  \"user\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/vouchers","description":"Create a voucher that entitles the recipient to one or more assets (ISBNs/SKUs).\n\nVouchers are scoped to the store associated with your API key. Once created, a voucher can be redeemed by the recipient via Snapplify's redemption flows; each redemption consumes one unit of `quantity`.\n\n### Body fields\n- `code` — the voucher code the recipient will redeem. If omitted, Snapplify generates one.\n- `reference` — your reference for this voucher (for reconciliation on your side)\n- `label` — display label shown to the recipient\n- `quantity` — how many times the voucher can be redeemed (default `1`)\n- `recipientEmail` — optional. If supplied, Snapplify will email the voucher to this address.\n- `assetIds` — list of asset identifiers (ISBN/SKU) the voucher grants access to\n- `redeem` — if `true`, auto-redeems the voucher immediately against `user`. Requires `user`.\n- `user` — Snapplify user id to auto-redeem against (required if `redeem=true`)\n\n### Errors\n- `400 Bad Request` — validation error (missing required field, invalid assetIds, duplicate code)\n- `403 Forbidden` — API key missing or invalid"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"BAD_REQUEST\",\n  \"message\": \"assetIds: must not be empty\"\n}"},{"id":"bdbf36ed-752f-47b7-95b1-3fc1e9cccee0","name":"403 Forbidden","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"body":{"mode":"raw","raw":"{\n  \"code\": \"SNAP-EXMPL-2024-A1B2\",\n  \"reference\": \"EXP-REF-00001\",\n  \"label\": \"Grade 10 Starter Pack\",\n  \"quantity\": 1,\n  \"recipientEmail\": \"student@example.com\",\n  \"assetIds\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ],\n  \"redeem\": false,\n  \"user\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/vouchers","description":"Create a voucher that entitles the recipient to one or more assets (ISBNs/SKUs).\n\nVouchers are scoped to the store associated with your API key. Once created, a voucher can be redeemed by the recipient via Snapplify's redemption flows; each redemption consumes one unit of `quantity`.\n\n### Body fields\n- `code` — the voucher code the recipient will redeem. If omitted, Snapplify generates one.\n- `reference` — your reference for this voucher (for reconciliation on your side)\n- `label` — display label shown to the recipient\n- `quantity` — how many times the voucher can be redeemed (default `1`)\n- `recipientEmail` — optional. If supplied, Snapplify will email the voucher to this address.\n- `assetIds` — list of asset identifiers (ISBN/SKU) the voucher grants access to\n- `redeem` — if `true`, auto-redeems the voucher immediately against `user`. Requires `user`.\n- `user` — Snapplify user id to auto-redeem against (required if `redeem=true`)\n\n### Errors\n- `400 Bad Request` — validation error (missing required field, invalid assetIds, duplicate code)\n- `403 Forbidden` — API key missing or invalid"},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"FORBIDDEN\",\n  \"message\": \"Bad credentials\"\n}"}],"_postman_id":"4c0cc6aa-1b99-456b-acbf-688450ed8b4f"},{"name":"List Vouchers","id":"87146211-5b95-4983-b15c-b07a84b6f13c","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/vouchers?page=0","description":"<p>List vouchers issued against your store (scoped by your API key).</p>\n<p>Results are paginated. Use <code>?page=N</code> to page through — page size is a server default and is not configurable by the caller. Iterate until the response is empty.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["vouchers"],"host":["https://api.snapplify.com"],"query":[{"description":{"content":"<p>Zero-indexed page number. Defaults to 0 if omitted.</p>\n","type":"text/plain"},"key":"page","value":"0"}],"variable":[]}},"response":[{"id":"1218278b-bb4c-4453-b03a-513b8a52054a","name":"200 OK","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"url":{"raw":"https://api.snapplify.com/vouchers?page=0","host":["https://api.snapplify.com"],"path":["vouchers"],"query":[{"key":"page","value":"0","description":"Zero-indexed page number. Defaults to 0 if omitted."}]},"description":"List vouchers issued against your store (scoped by your API key).\n\nResults are paginated. Use `?page=N` to page through — page size is a server default and is not configurable by the caller. Iterate until the response is empty."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n  {\n    \"label\": \"Grade 10 Starter Pack\",\n    \"code\": \"SNAP-EXMPL-2024-A1B2\",\n    \"reference\": \"EXP-REF-00001\",\n    \"quantity\": 1,\n    \"quantityRemaining\": 1,\n    \"recipientEmail\": \"student@example.com\",\n    \"assetIds\": [\n      \"9781234567890\",\n      \"9781234567906\"\n    ],\n    \"activatedDate\": null,\n    \"createdDate\": \"2024-06-15T10:30:00.000Z\"\n  },\n  {\n    \"label\": \"Grade 10 Starter Pack\",\n    \"code\": \"SNAP-EXMPL-2024-C3D4\",\n    \"reference\": \"EXP-REF-00002\",\n    \"quantity\": 1,\n    \"quantityRemaining\": 1,\n    \"recipientEmail\": \"student2@example.com\",\n    \"assetIds\": [\n      \"9781234567890\",\n      \"9781234567906\"\n    ],\n    \"activatedDate\": null,\n    \"createdDate\": \"2024-06-15T10:30:00.000Z\"\n  }\n]"}],"_postman_id":"87146211-5b95-4983-b15c-b07a84b6f13c"},{"name":"Get Voucher by Code","id":"84f5a191-c5cb-41cf-be7e-e57ba1b7e10c","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/vouchers/:code","description":"<p>Retrieve a single voucher by its code.</p>\n<p><code>quantityRemaining</code> shows how many redemptions are left on the voucher. <code>activatedDate</code> is the timestamp of the first redemption (or <code>null</code> if never redeemed).</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["vouchers",":code"],"host":["https://api.snapplify.com"],"query":[],"variable":[{"description":{"content":"<p>The voucher code.</p>\n","type":"text/plain"},"type":"any","value":"SNAP-EXMPL-2024-A1B2","key":"code"}]}},"response":[{"id":"738abfbb-f034-461d-8761-110fcad3b5c5","name":"200 OK","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"url":{"raw":"https://api.snapplify.com/vouchers/:code","host":["https://api.snapplify.com"],"path":["vouchers",":code"],"variable":[{"key":"code","value":"SNAP-EXMPL-2024-A1B2","description":"The voucher code."}]},"description":"Retrieve a single voucher by its code.\n\n`quantityRemaining` shows how many redemptions are left on the voucher. `activatedDate` is the timestamp of the first redemption (or `null` if never redeemed)."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"label\": \"Grade 10 Starter Pack\",\n  \"code\": \"SNAP-EXMPL-2024-A1B2\",\n  \"reference\": \"EXP-REF-00001\",\n  \"quantity\": 1,\n  \"quantityRemaining\": 1,\n  \"recipientEmail\": \"student@example.com\",\n  \"assetIds\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ],\n  \"activatedDate\": null,\n  \"createdDate\": \"2024-06-15T10:30:00.000Z\"\n}"},{"id":"e9f8c212-4223-44c2-ba70-0a5a4ae1cf45","name":"200 OK — Fully Redeemed","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"url":{"raw":"https://api.snapplify.com/vouchers/:code","host":["https://api.snapplify.com"],"path":["vouchers",":code"],"variable":[{"key":"code","value":"SNAP-EXMPL-2024-A1B2","description":"The voucher code."}]},"description":"Retrieve a single voucher by its code.\n\n`quantityRemaining` shows how many redemptions are left on the voucher. `activatedDate` is the timestamp of the first redemption (or `null` if never redeemed)."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"label\": \"Grade 10 Starter Pack\",\n  \"code\": \"SNAP-EXMPL-2024-A1B2\",\n  \"reference\": \"EXP-REF-00001\",\n  \"quantity\": 1,\n  \"quantityRemaining\": 0,\n  \"recipientEmail\": \"student@example.com\",\n  \"assetIds\": [\n    \"9781234567890\",\n    \"9781234567906\"\n  ],\n  \"activatedDate\": \"2024-06-15T10:30:15.000Z\",\n  \"createdDate\": \"2024-06-15T10:30:00.000Z\"\n}"},{"id":"46db355b-10c5-40ff-9c95-79f5f317e3a7","name":"404 Not Found","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"url":{"raw":"https://api.snapplify.com/vouchers/:code","host":["https://api.snapplify.com"],"path":["vouchers",":code"],"variable":[{"key":"code","value":"SNAP-EXMPL-2024-A1B2","description":"The voucher code."}]},"description":"Retrieve a single voucher by its code.\n\n`quantityRemaining` shows how many redemptions are left on the voucher. `activatedDate` is the timestamp of the first redemption (or `null` if never redeemed)."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"NOT_FOUND\",\n  \"message\": \"Voucher not found\"\n}"}],"_postman_id":"84f5a191-c5cb-41cf-be7e-e57ba1b7e10c"},{"name":"Get Voucher Redemptions","id":"d8f98e76-dbe2-4199-8019-8adfbb5cfea4","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/vouchers/:code/redemptions?page=0","description":"<p>List the redemptions that have been made against a voucher.</p>\n<p>Each entry records when a redemption occurred and the email address of the redeeming user. Use <code>quantity - quantityRemaining</code> (from the voucher itself) to know the total count without paging the full history.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["vouchers",":code","redemptions"],"host":["https://api.snapplify.com"],"query":[{"description":{"content":"<p>Zero-indexed page number.</p>\n","type":"text/plain"},"key":"page","value":"0"}],"variable":[{"description":{"content":"<p>The voucher code.</p>\n","type":"text/plain"},"type":"any","value":"SNAP-EXMPL-2024-A1B2","key":"code"}]}},"response":[{"id":"4b25a7c0-7268-4dcc-921e-19551af9532a","name":"200 OK","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"url":{"raw":"https://api.snapplify.com/vouchers/:code/redemptions?page=0","host":["https://api.snapplify.com"],"path":["vouchers",":code","redemptions"],"query":[{"key":"page","value":"0","description":"Zero-indexed page number."}],"variable":[{"key":"code","value":"SNAP-EXMPL-2024-A1B2","description":"The voucher code."}]},"description":"List the redemptions that have been made against a voucher.\n\nEach entry records when a redemption occurred and the email address of the redeeming user. Use `quantity - quantityRemaining` (from the voucher itself) to know the total count without paging the full history."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n  {\n    \"createdDate\": \"2024-06-15T10:30:15.000Z\",\n    \"email\": \"student@example.com\"\n  }\n]"},{"id":"c4d609e7-5ba9-483d-a88a-aeb57035d6cf","name":"200 OK — None Yet","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"url":{"raw":"https://api.snapplify.com/vouchers/:code/redemptions?page=0","host":["https://api.snapplify.com"],"path":["vouchers",":code","redemptions"],"query":[{"key":"page","value":"0","description":"Zero-indexed page number."}],"variable":[{"key":"code","value":"SNAP-EXMPL-2024-A1B2","description":"The voucher code."}]},"description":"List the redemptions that have been made against a voucher.\n\nEach entry records when a redemption occurred and the email address of the redeeming user. Use `quantity - quantityRemaining` (from the voucher itself) to know the total count without paging the full history."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[]"},{"id":"e4ab378e-c571-4cd3-9803-ee52686219a6","name":"404 Not Found","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"url":{"raw":"https://api.snapplify.com/vouchers/:code/redemptions?page=0","host":["https://api.snapplify.com"],"path":["vouchers",":code","redemptions"],"query":[{"key":"page","value":"0","description":"Zero-indexed page number."}],"variable":[{"key":"code","value":"SNAP-EXMPL-2024-A1B2","description":"The voucher code."}]},"description":"List the redemptions that have been made against a voucher.\n\nEach entry records when a redemption occurred and the email address of the redeeming user. Use `quantity - quantityRemaining` (from the voucher itself) to know the total count without paging the full history."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"NOT_FOUND\",\n  \"message\": \"Voucher not found\"\n}"}],"_postman_id":"d8f98e76-dbe2-4199-8019-8adfbb5cfea4"}],"id":"8a9462fe-6a59-42fb-914f-810b1b90915d","description":"<p>The <strong>Snapplify Voucher API</strong> lets your store issue vouchers that entitle recipients to one or more assets (ISBNs/SKUs). Vouchers can be emailed to a recipient for self-redemption, or auto-redeemed against a specific user at creation time.</p>\n<h3 id=\"authentication\">Authentication</h3>\n<p>All endpoints require an API key in the <code>apiKey</code> request header. API keys are issued during onboarding and scope you to a specific store. All data returned is automatically filtered to that store — you cannot read other stores' vouchers.</p>\n<p>(For backwards compatibility the headers <code>Token</code>, <code>AuthToken</code>, and <code>authToken</code> are also accepted, but new integrations should use <code>apiKey</code>.)</p>\n<h3 id=\"pagination\">Pagination</h3>\n<p>List endpoints (<code>List Vouchers</code>, <code>Get Voucher Redemptions</code>) are paginated via <code>?page=N</code>. Page size is server-controlled and not adjustable by the caller. Page until an empty response to iterate everything.</p>\n<h3 id=\"lifecycle\">Lifecycle</h3>\n<ul>\n<li>A voucher is created with a <code>quantity</code> (default 1).</li>\n<li>Each redemption decrements <code>quantityRemaining</code> and appends to the voucher's redemption history.</li>\n<li>When <code>quantityRemaining</code> hits 0, the voucher is fully redeemed and cannot be used again.</li>\n<li>Use <code>redeem: true</code> (with <code>user</code>) at creation time to auto-redeem without involving an email flow.</li>\n</ul>\n","event":[{"listen":"prerequest","script":{"id":"5c7cc15b-8632-49f3-8b56-9a3867c03b6e","type":"text/javascript","packages":{},"requests":{},"exec":[""]}},{"listen":"test","script":{"id":"cb0518c7-5ed1-45fd-8f2a-6b2260e290f7","type":"text/javascript","packages":{},"requests":{},"exec":[""]}}],"_postman_id":"8a9462fe-6a59-42fb-914f-810b1b90915d","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}}},{"name":"Snapplify Order API","item":[{"name":"Create Order","id":"13f8d415-40f8-4214-9151-2c792654da14","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"client\": \"example-store\",\n  \"source\": \"ORDER_BOOKBUDDY_RETAIL\",\n  \"reference\": \"EXP-ORD-2024-001234\",\n  \"orderState\": \"COMPLETED\",\n  \"paymentState\": \"PAID\",\n  \"paymentMethod\": \"CARD\",\n  \"paymentGateway\": \"snapplify-pay\",\n  \"items\": [\n    {\n      \"amount\": 199.99,\n      \"currency\": \"ZAR\",\n      \"itemId\": \"9781234567890\",\n      \"itemName\": \"Example Book Title\",\n      \"quantity\": 1\n    }\n  ],\n  \"vouchers\": [\n    {\n      \"type\": \"DISCOUNT\",\n      \"label\": \"Spring Promo\",\n      \"code\": \"SPRING10\",\n      \"amount\": 20.0\n    }\n  ],\n  \"completedDate\": \"2024-06-15T10:30:00.000Z\",\n  \"userId\": 1001\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/orders","description":"<p>Create an order in Snapplify from your store.</p>\n<p>Idempotent on <code>reference</code> — submitting the same <code>reference</code> twice updates the existing order rather than creating a duplicate. Use a stable, unique reference per order on your side.</p>\n<h3 id=\"required-fields\">Required fields</h3>\n<ul>\n<li><code>reference</code> — your unique order identifier</li>\n<li><code>orderState</code> — one of <code>NEW</code>, <code>COMPLETED</code>, <code>CANCELLED</code>, <code>PENDING</code>, <code>ERROR</code></li>\n<li><code>paymentState</code> — your payment state string (e.g. <code>PAID</code>, <code>UNPAID</code>, <code>REFUNDED</code>)</li>\n<li><code>paymentMethod</code> — your payment method string</li>\n<li><code>items[]</code> — at least one item with <code>amount</code>, <code>currency</code>, <code>itemId</code> (ISBN/SKU), <code>itemName</code>, <code>quantity</code></li>\n<li><code>completedDate</code> — ISO-8601 timestamp</li>\n<li><code>userId</code> — Snapplify user id of the buyer</li>\n</ul>\n<h3 id=\"optional\">Optional</h3>\n<ul>\n<li><code>client</code> — identifier for the originating client/system</li>\n<li><code>source</code> — order source tag; defaults to <code>ORDER_BOOKBUDDY_RETAIL</code> if omitted</li>\n<li><code>paymentGateway</code> — gateway used for payment</li>\n<li><code>vouchers[]</code> — voucher applications (<code>type</code>, <code>label</code>, <code>code</code>, <code>amount</code>)</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["orders"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"4faf1a31-0d71-4c0d-9024-aa420aa1d0eb","name":"200 OK","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"body":{"mode":"raw","raw":"{\n  \"client\": \"example-store\",\n  \"source\": \"ORDER_BOOKBUDDY_RETAIL\",\n  \"reference\": \"EXP-ORD-2024-001234\",\n  \"orderState\": \"COMPLETED\",\n  \"paymentState\": \"PAID\",\n  \"paymentMethod\": \"CARD\",\n  \"paymentGateway\": \"snapplify-pay\",\n  \"items\": [\n    {\n      \"amount\": 199.99,\n      \"currency\": \"ZAR\",\n      \"itemId\": \"9781234567890\",\n      \"itemName\": \"Example Book Title\",\n      \"quantity\": 1\n    }\n  ],\n  \"vouchers\": [\n    {\n      \"type\": \"DISCOUNT\",\n      \"label\": \"Spring Promo\",\n      \"code\": \"SPRING10\",\n      \"amount\": 20.0\n    }\n  ],\n  \"completedDate\": \"2024-06-15T10:30:00.000Z\",\n  \"userId\": 1001\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/orders","description":"Create an order in Snapplify from your store.\n\nIdempotent on `reference` — submitting the same `reference` twice updates the existing order rather than creating a duplicate. Use a stable, unique reference per order on your side.\n\n### Required fields\n- `reference` — your unique order identifier\n- `orderState` — one of `NEW`, `COMPLETED`, `CANCELLED`, `PENDING`, `ERROR`\n- `paymentState` — your payment state string (e.g. `PAID`, `UNPAID`, `REFUNDED`)\n- `paymentMethod` — your payment method string\n- `items[]` — at least one item with `amount`, `currency`, `itemId` (ISBN/SKU), `itemName`, `quantity`\n- `completedDate` — ISO-8601 timestamp\n- `userId` — Snapplify user id of the buyer\n\n### Optional\n- `client` — identifier for the originating client/system\n- `source` — order source tag; defaults to `ORDER_BOOKBUDDY_RETAIL` if omitted\n- `paymentGateway` — gateway used for payment\n- `vouchers[]` — voucher applications (`type`, `label`, `code`, `amount`)"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"id\": 5567890,\n  \"reference\": \"EXP-ORD-2024-001234\",\n  \"orderState\": \"COMPLETED\",\n  \"paymentState\": \"PAID\",\n  \"paymentMethod\": \"CARD\",\n  \"completedDate\": \"2024-06-15T10:30:00.000Z\",\n  \"items\": [\n    {\n      \"id\": 7788001,\n      \"amount\": 199.99,\n      \"currency\": \"ZAR\",\n      \"itemId\": \"9781234567890\",\n      \"itemName\": \"Example Book Title\",\n      \"quantity\": 1\n    }\n  ]\n}"},{"id":"c92d9690-cda8-4d7e-9a1d-518da5ddb116","name":"400 Bad Request","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"body":{"mode":"raw","raw":"{\n  \"client\": \"example-store\",\n  \"source\": \"ORDER_BOOKBUDDY_RETAIL\",\n  \"reference\": \"EXP-ORD-2024-001234\",\n  \"orderState\": \"COMPLETED\",\n  \"paymentState\": \"PAID\",\n  \"paymentMethod\": \"CARD\",\n  \"paymentGateway\": \"snapplify-pay\",\n  \"items\": [\n    {\n      \"amount\": 199.99,\n      \"currency\": \"ZAR\",\n      \"itemId\": \"9781234567890\",\n      \"itemName\": \"Example Book Title\",\n      \"quantity\": 1\n    }\n  ],\n  \"vouchers\": [\n    {\n      \"type\": \"DISCOUNT\",\n      \"label\": \"Spring Promo\",\n      \"code\": \"SPRING10\",\n      \"amount\": 20.0\n    }\n  ],\n  \"completedDate\": \"2024-06-15T10:30:00.000Z\",\n  \"userId\": 1001\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/orders","description":"Create an order in Snapplify from your store.\n\nIdempotent on `reference` — submitting the same `reference` twice updates the existing order rather than creating a duplicate. Use a stable, unique reference per order on your side.\n\n### Required fields\n- `reference` — your unique order identifier\n- `orderState` — one of `NEW`, `COMPLETED`, `CANCELLED`, `PENDING`, `ERROR`\n- `paymentState` — your payment state string (e.g. `PAID`, `UNPAID`, `REFUNDED`)\n- `paymentMethod` — your payment method string\n- `items[]` — at least one item with `amount`, `currency`, `itemId` (ISBN/SKU), `itemName`, `quantity`\n- `completedDate` — ISO-8601 timestamp\n- `userId` — Snapplify user id of the buyer\n\n### Optional\n- `client` — identifier for the originating client/system\n- `source` — order source tag; defaults to `ORDER_BOOKBUDDY_RETAIL` if omitted\n- `paymentGateway` — gateway used for payment\n- `vouchers[]` — voucher applications (`type`, `label`, `code`, `amount`)"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": \"validation\",\n  \"message\": \"items must not be empty\"\n}"},{"id":"d10a35f9-e150-42e0-9c8e-b6148f4134f0","name":"403 Forbidden","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"body":{"mode":"raw","raw":"{\n  \"client\": \"example-store\",\n  \"source\": \"ORDER_BOOKBUDDY_RETAIL\",\n  \"reference\": \"EXP-ORD-2024-001234\",\n  \"orderState\": \"COMPLETED\",\n  \"paymentState\": \"PAID\",\n  \"paymentMethod\": \"CARD\",\n  \"paymentGateway\": \"snapplify-pay\",\n  \"items\": [\n    {\n      \"amount\": 199.99,\n      \"currency\": \"ZAR\",\n      \"itemId\": \"9781234567890\",\n      \"itemName\": \"Example Book Title\",\n      \"quantity\": 1\n    }\n  ],\n  \"vouchers\": [\n    {\n      \"type\": \"DISCOUNT\",\n      \"label\": \"Spring Promo\",\n      \"code\": \"SPRING10\",\n      \"amount\": 20.0\n    }\n  ],\n  \"completedDate\": \"2024-06-15T10:30:00.000Z\",\n  \"userId\": 1001\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/orders","description":"Create an order in Snapplify from your store.\n\nIdempotent on `reference` — submitting the same `reference` twice updates the existing order rather than creating a duplicate. Use a stable, unique reference per order on your side.\n\n### Required fields\n- `reference` — your unique order identifier\n- `orderState` — one of `NEW`, `COMPLETED`, `CANCELLED`, `PENDING`, `ERROR`\n- `paymentState` — your payment state string (e.g. `PAID`, `UNPAID`, `REFUNDED`)\n- `paymentMethod` — your payment method string\n- `items[]` — at least one item with `amount`, `currency`, `itemId` (ISBN/SKU), `itemName`, `quantity`\n- `completedDate` — ISO-8601 timestamp\n- `userId` — Snapplify user id of the buyer\n\n### Optional\n- `client` — identifier for the originating client/system\n- `source` — order source tag; defaults to `ORDER_BOOKBUDDY_RETAIL` if omitted\n- `paymentGateway` — gateway used for payment\n- `vouchers[]` — voucher applications (`type`, `label`, `code`, `amount`)"},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": \"Bad credentials\"\n}"}],"_postman_id":"13f8d415-40f8-4214-9151-2c792654da14"},{"name":"Get Order","id":"cb3ba073-130d-4575-a7a2-f7bd8d2074a6","request":{"method":"GET","header":[],"url":"https://api.snapplify.com/orders/:id","description":"<p>Retrieve a single order by reference.</p>\n<p>Returns the current state of the order including items, vouchers, payment status, and completion timestamp.</p>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["orders",":id"],"host":["https://api.snapplify.com"],"query":[],"variable":[{"description":{"content":"<p>Your order reference.</p>\n","type":"text/plain"},"type":"any","value":"EXP-ORD-2024-001234","key":"id"}]}},"response":[{"id":"9aa48b1f-62b1-459d-9b8d-77d656a5f967","name":"200 OK","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/orders/:id","host":["https://api.snapplify.com"],"path":["orders",":id"],"variable":[{"key":"id","value":"EXP-ORD-2024-001234","description":"Your order reference."}]},"description":"Retrieve a single order by reference.\n\nReturns the current state of the order including items, vouchers, payment status, and completion timestamp."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"id\": 5567890,\n  \"reference\": \"EXP-ORD-2024-001234\",\n  \"orderState\": \"COMPLETED\",\n  \"paymentState\": \"PAID\",\n  \"paymentMethod\": \"CARD\",\n  \"completedDate\": \"2024-06-15T10:30:00.000Z\",\n  \"items\": [\n    {\n      \"id\": 7788001,\n      \"amount\": 199.99,\n      \"currency\": \"ZAR\",\n      \"itemId\": \"9781234567890\",\n      \"itemName\": \"Example Book Title\",\n      \"quantity\": 1\n    }\n  ]\n}"},{"id":"a48ef037-a6c7-4f37-96fa-4259497e142e","name":"404 Not Found","originalRequest":{"method":"GET","header":[{"key":"apiKey","value":"{{api_key}}","description":"Required. Your Snapplify-issued API key."}],"url":{"raw":"https://api.snapplify.com/orders/:id","host":["https://api.snapplify.com"],"path":["orders",":id"],"variable":[{"key":"id","value":"EXP-ORD-2024-001234","description":"Your order reference."}]},"description":"Retrieve a single order by reference.\n\nReturns the current state of the order including items, vouchers, payment status, and completion timestamp."},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": \"order not found\"\n}"}],"_postman_id":"cb3ba073-130d-4575-a7a2-f7bd8d2074a6"},{"name":"Update Order Status","id":"5d263ff7-a959-40a7-8cf0-cc70e963c65d","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"reference\": \"EXP-ORD-2024-001234\",\n  \"status\": \"COMPLETED\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/order/status","description":"<p><strong>Available to specific partners only — contact Snapplify to request access.</strong></p>\n<p>Update the lifecycle status of an existing order, looked up by <code>reference</code>.</p>\n<h3 id=\"required-fields\">Required fields</h3>\n<ul>\n<li><code>reference</code> — the order reference you supplied when creating the order</li>\n<li><code>status</code> — one of <code>NEW</code>, <code>COMPLETED</code>, <code>CANCELLED</code>, <code>PENDING</code>, <code>ERROR</code></li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["order","status"],"host":["https://api.snapplify.com"],"query":[],"variable":[]}},"response":[{"id":"4d556e9f-f6b9-41cd-91b4-662347160229","name":"200 OK","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"body":{"mode":"raw","raw":"{\n  \"reference\": \"EXP-ORD-2024-001234\",\n  \"status\": \"COMPLETED\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/order/status","description":"**Available to specific partners only — contact Snapplify to request access.**\n\nUpdate the lifecycle status of an existing order, looked up by `reference`.\n\n### Required fields\n- `reference` — the order reference you supplied when creating the order\n- `status` — one of `NEW`, `COMPLETED`, `CANCELLED`, `PENDING`, `ERROR`"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":""},{"id":"70d489f1-2fe8-4185-9180-4a3108522e77","name":"404 Not Found","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"body":{"mode":"raw","raw":"{\n  \"reference\": \"EXP-ORD-2024-001234\",\n  \"status\": \"COMPLETED\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/order/status","description":"**Available to specific partners only — contact Snapplify to request access.**\n\nUpdate the lifecycle status of an existing order, looked up by `reference`.\n\n### Required fields\n- `reference` — the order reference you supplied when creating the order\n- `status` — one of `NEW`, `COMPLETED`, `CANCELLED`, `PENDING`, `ERROR`"},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": \"order not found\"\n}"},{"id":"05a8535b-c143-4ffc-aa7a-a011070ad070","name":"403 Forbidden","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"body":{"mode":"raw","raw":"{\n  \"reference\": \"EXP-ORD-2024-001234\",\n  \"status\": \"COMPLETED\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/order/status","description":"**Available to specific partners only — contact Snapplify to request access.**\n\nUpdate the lifecycle status of an existing order, looked up by `reference`.\n\n### Required fields\n- `reference` — the order reference you supplied when creating the order\n- `status` — one of `NEW`, `COMPLETED`, `CANCELLED`, `PENDING`, `ERROR`"},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": \"not authorised for this endpoint\"\n}"}],"_postman_id":"5d263ff7-a959-40a7-8cf0-cc70e963c65d"},{"name":"Update Order Item","id":"fef2996a-52a8-44ee-8344-522c240c6de9","request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"orderItemReference\": \"EXP-ORD-2024-001234-1\",\n  \"orderItemMessage\": \"Shipped via courier\",\n  \"trackingUrl\": \"https://courier.example.com/track/ABC123\",\n  \"trackingReference\": \"ABC123\",\n  \"orderStatusDate\": \"2024-06-16T08:00:00.000Z\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.snapplify.com/order/:id","description":"<p><strong>Available to specific partners only — contact Snapplify to request access.</strong></p>\n<p>Append a fulfilment / tracking update to an order item. Each call adds a note record to the item; previous notes are preserved.</p>\n<h3 id=\"body-fields-all-optional-supply-what-you-have\">Body fields (all optional, supply what you have)</h3>\n<ul>\n<li><code>orderItemReference</code> — the specific item reference</li>\n<li><code>orderItemMessage</code> — free-text message (e.g. shipping notes)</li>\n<li><code>trackingUrl</code> — courier tracking URL the buyer can follow</li>\n<li><code>trackingReference</code> — courier tracking number</li>\n<li><code>orderStatusDate</code> — ISO-8601 timestamp for this update</li>\n</ul>\n","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}},"urlObject":{"path":["order",":id"],"host":["https://api.snapplify.com"],"query":[],"variable":[{"description":{"content":"<p>The order reference.</p>\n","type":"text/plain"},"type":"any","value":"EXP-ORD-2024-001234","key":"id"}]}},"response":[{"id":"fdb72a08-17d9-4c57-9a1b-c03d47f82221","name":"200 OK","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"body":{"mode":"raw","raw":"{\n  \"orderItemReference\": \"EXP-ORD-2024-001234-1\",\n  \"orderItemMessage\": \"Shipped via courier\",\n  \"trackingUrl\": \"https://courier.example.com/track/ABC123\",\n  \"trackingReference\": \"ABC123\",\n  \"orderStatusDate\": \"2024-06-16T08:00:00.000Z\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://api.snapplify.com/order/:id","host":["https://api.snapplify.com"],"path":["order",":id"],"variable":[{"key":"id","value":"EXP-ORD-2024-001234","description":"The order reference."}]},"description":"**Available to specific partners only — contact Snapplify to request access.**\n\nAppend a fulfilment / tracking update to an order item. Each call adds a note record to the item; previous notes are preserved.\n\n### Body fields (all optional, supply what you have)\n- `orderItemReference` — the specific item reference\n- `orderItemMessage` — free-text message (e.g. shipping notes)\n- `trackingUrl` — courier tracking URL the buyer can follow\n- `trackingReference` — courier tracking number\n- `orderStatusDate` — ISO-8601 timestamp for this update"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":""},{"id":"d694dafe-71aa-4e16-8519-bebe2cffac16","name":"404 Not Found","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"body":{"mode":"raw","raw":"{\n  \"orderItemReference\": \"EXP-ORD-2024-001234-1\",\n  \"orderItemMessage\": \"Shipped via courier\",\n  \"trackingUrl\": \"https://courier.example.com/track/ABC123\",\n  \"trackingReference\": \"ABC123\",\n  \"orderStatusDate\": \"2024-06-16T08:00:00.000Z\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://api.snapplify.com/order/:id","host":["https://api.snapplify.com"],"path":["order",":id"],"variable":[{"key":"id","value":"EXP-ORD-2024-001234","description":"The order reference."}]},"description":"**Available to specific partners only — contact Snapplify to request access.**\n\nAppend a fulfilment / tracking update to an order item. Each call adds a note record to the item; previous notes are preserved.\n\n### Body fields (all optional, supply what you have)\n- `orderItemReference` — the specific item reference\n- `orderItemMessage` — free-text message (e.g. shipping notes)\n- `trackingUrl` — courier tracking URL the buyer can follow\n- `trackingReference` — courier tracking number\n- `orderStatusDate` — ISO-8601 timestamp for this update"},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": \"order not found\"\n}"},{"id":"b12b0125-4e89-4716-a1b9-80a144281942","name":"403 Forbidden","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"{{api_key}}","description":"Required."}],"body":{"mode":"raw","raw":"{\n  \"orderItemReference\": \"EXP-ORD-2024-001234-1\",\n  \"orderItemMessage\": \"Shipped via courier\",\n  \"trackingUrl\": \"https://courier.example.com/track/ABC123\",\n  \"trackingReference\": \"ABC123\",\n  \"orderStatusDate\": \"2024-06-16T08:00:00.000Z\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://api.snapplify.com/order/:id","host":["https://api.snapplify.com"],"path":["order",":id"],"variable":[{"key":"id","value":"EXP-ORD-2024-001234","description":"The order reference."}]},"description":"**Available to specific partners only — contact Snapplify to request access.**\n\nAppend a fulfilment / tracking update to an order item. Each call adds a note record to the item; previous notes are preserved.\n\n### Body fields (all optional, supply what you have)\n- `orderItemReference` — the specific item reference\n- `orderItemMessage` — free-text message (e.g. shipping notes)\n- `trackingUrl` — courier tracking URL the buyer can follow\n- `trackingReference` — courier tracking number\n- `orderStatusDate` — ISO-8601 timestamp for this update"},"status":"Forbidden","code":403,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": \"not authorised for this endpoint\"\n}"}],"_postman_id":"fef2996a-52a8-44ee-8344-522c240c6de9"}],"id":"f33e5d69-cf03-4eeb-bc5e-87f20b45ef8d","description":"<p>The <strong>Snapplify Order API</strong> lets your store create orders in Snapplify and (for selected partners) push fulfilment updates back as the order moves through your pipeline.</p>\n<h3 id=\"authentication\">Authentication</h3>\n<p>All endpoints require an API key, sent in the <code>apiKey</code> request header. API keys are issued during onboarding. (For backwards compatibility the headers <code>Token</code>, <code>AuthToken</code>, and <code>authToken</code> are also accepted, but new integrations should use <code>apiKey</code>.)</p>\n<h3 id=\"order-status-values\">Order status values</h3>\n<p><code>NEW</code>, <code>COMPLETED</code>, <code>CANCELLED</code>, <code>PENDING</code>, <code>ERROR</code> — used in <code>orderState</code> (Create Order) and <code>status</code> (Update Order Status).</p>\n<h3 id=\"partner-restricted-endpoints\">Partner-restricted endpoints</h3>\n<p><strong>Update Order Status</strong> and <strong>Update Order Item</strong> are restricted to specific partners. If you need access, contact Snapplify.</p>\n","_postman_id":"f33e5d69-cf03-4eeb-bc5e-87f20b45ef8d","auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]},"isInherited":true,"source":{"_postman_id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","id":"dc864ebd-d883-4286-b4c2-bc9619a75ce4","name":"Snapplify Cloud Services API","type":"collection"}}},{"name":"Snapplify Pay","item":[{"name":"Begin Payment","id":"bad36309-69d1-49a9-b46b-a675b0674296","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"amount\": 199.99,\n  \"currency\": \"ZAR\",\n  \"country\": \"ZA\",\n  \"referenceCode\": \"EXP-ORD-2024-001234\",\n  \"redirectUrl\": \"https://example.com/checkout/return\",\n  \"notificationUrl\": \"https://example.com/webhooks/snapplify-pay\",\n  \"declinedUrl\": \"https://example.com/checkout/declined\",\n  \"cancelUrl\": \"https://example.com/checkout/cancelled\",\n  \"backUrl\": \"https://example.com/checkout\",\n  \"description\": \"Example Book Title x 1\",\n  \"customerId\": 1001,\n  \"storeId\": 501,\n  \"allowPartialPayment\": false\n}","options":{"raw":{"language":"json"}}},"url":"https://pay.snapplify.com/payment/request?client={{pay_client}}&secret={{pay_secret}}","description":"<p>Start a new payment. You POST the payment details to Snapplify Pay; Snapplify returns a <code>token</code> and a <code>redirectUrl</code>. Redirect the user's browser to <code>redirectUrl</code> to complete payment on Snapplify Pay's hosted form. After the gateway completes (success, cancel, or decline), the user is redirected back to the URL(s) you supplied on this request.</p>\n<h3 id=\"required\">Required</h3>\n<ul>\n<li><code>amount</code> — decimal, in the specified <code>currency</code></li>\n<li><code>currency</code> — ISO-4217 currency code (e.g. <code>ZAR</code>)</li>\n<li><code>country</code> — ISO-3166 alpha-2 country code (e.g. <code>ZA</code>)</li>\n<li><code>redirectUrl</code> — where to send the user after a <strong>successful</strong> payment</li>\n</ul>\n<h3 id=\"optional\">Optional</h3>\n<ul>\n<li><code>referenceCode</code> — your reference for this payment (echoed back on validate + webhook). Use a stable unique value to reconcile on your side.</li>\n<li><code>notificationUrl</code> — webhook URL Snapplify will POST the <code>token</code> to once the payment completes. See <strong>Payment Completion</strong> in this folder.</li>\n<li><code>declinedUrl</code> — where to send the user if the payment is declined</li>\n<li><code>cancelUrl</code> — where to send the user if they cancel at the gateway</li>\n<li><code>backUrl</code> — where to send the user if they click back on the payment form</li>\n<li><code>description</code> — free-text shown to the payer</li>\n<li><code>customerId</code>, <code>storeId</code> — optional Snapplify IDs to associate the payment with</li>\n<li><code>allowPartialPayment</code> — defaults to <code>false</code></li>\n</ul>\n<h3 id=\"error-codes\">Error codes</h3>\n<ul>\n<li><code>100</code> — invalid client or secret</li>\n<li><code>110</code> — invalid token, payment, or state</li>\n</ul>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"42bbf2a0-5276-4013-8e23-5ab1e5b4b9dd","id":"42bbf2a0-5276-4013-8e23-5ab1e5b4b9dd","name":"Snapplify Pay","type":"folder"}},"urlObject":{"path":["payment","request"],"host":["https://pay.snapplify.com"],"query":[{"description":{"content":"<p>Required. Your Snapplify-issued Pay client identifier.</p>\n","type":"text/plain"},"key":"client","value":"{{pay_client}}"},{"description":{"content":"<p>Required. Your Snapplify-issued Pay secret. See auth notes — sent in the query string.</p>\n","type":"text/plain"},"key":"secret","value":"{{pay_secret}}"}],"variable":[]}},"response":[{"id":"97c6be6e-488e-470c-b864-683e78c8eaf8","name":"200 OK","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"amount\": 199.99,\n  \"currency\": \"ZAR\",\n  \"country\": \"ZA\",\n  \"referenceCode\": \"EXP-ORD-2024-001234\",\n  \"redirectUrl\": \"https://example.com/checkout/return\",\n  \"notificationUrl\": \"https://example.com/webhooks/snapplify-pay\",\n  \"declinedUrl\": \"https://example.com/checkout/declined\",\n  \"cancelUrl\": \"https://example.com/checkout/cancelled\",\n  \"backUrl\": \"https://example.com/checkout\",\n  \"description\": \"Example Book Title x 1\",\n  \"customerId\": 1001,\n  \"storeId\": 501,\n  \"allowPartialPayment\": false\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://pay.snapplify.com/payment/request?client={{pay_client}}&secret={{pay_secret}}","host":["https://pay.snapplify.com"],"path":["payment","request"],"query":[{"key":"client","value":"{{pay_client}}","description":"Required. Your Snapplify-issued Pay client identifier."},{"key":"secret","value":"{{pay_secret}}","description":"Required. Your Snapplify-issued Pay secret. See auth notes — sent in the query string."}]},"description":"Start a new payment. You POST the payment details to Snapplify Pay; Snapplify returns a `token` and a `redirectUrl`. Redirect the user's browser to `redirectUrl` to complete payment on Snapplify Pay's hosted form. After the gateway completes (success, cancel, or decline), the user is redirected back to the URL(s) you supplied on this request.\n\n### Required\n- `amount` — decimal, in the specified `currency`\n- `currency` — ISO-4217 currency code (e.g. `ZAR`)\n- `country` — ISO-3166 alpha-2 country code (e.g. `ZA`)\n- `redirectUrl` — where to send the user after a **successful** payment\n\n### Optional\n- `referenceCode` — your reference for this payment (echoed back on validate + webhook). Use a stable unique value to reconcile on your side.\n- `notificationUrl` — webhook URL Snapplify will POST the `token` to once the payment completes. See **Payment Completion** in this folder.\n- `declinedUrl` — where to send the user if the payment is declined\n- `cancelUrl` — where to send the user if they cancel at the gateway\n- `backUrl` — where to send the user if they click back on the payment form\n- `description` — free-text shown to the payer\n- `customerId`, `storeId` — optional Snapplify IDs to associate the payment with\n- `allowPartialPayment` — defaults to `false`\n\n### Error codes\n- `100` — invalid client or secret\n- `110` — invalid token, payment, or state"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"token\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n  \"redirectUrl\": \"https://pay.snapplify.com/payment/submit?client={{pay_client}}&token=c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\"\n}"},{"id":"5e48ccdb-d85f-40b6-8e1b-b1d7224655c1","name":"401 Unauthorized — Bad credentials","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"amount\": 199.99,\n  \"currency\": \"ZAR\",\n  \"country\": \"ZA\",\n  \"referenceCode\": \"EXP-ORD-2024-001234\",\n  \"redirectUrl\": \"https://example.com/checkout/return\",\n  \"notificationUrl\": \"https://example.com/webhooks/snapplify-pay\",\n  \"declinedUrl\": \"https://example.com/checkout/declined\",\n  \"cancelUrl\": \"https://example.com/checkout/cancelled\",\n  \"backUrl\": \"https://example.com/checkout\",\n  \"description\": \"Example Book Title x 1\",\n  \"customerId\": 1001,\n  \"storeId\": 501,\n  \"allowPartialPayment\": false\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://pay.snapplify.com/payment/request?client={{pay_client}}&secret={{pay_secret}}","host":["https://pay.snapplify.com"],"path":["payment","request"],"query":[{"key":"client","value":"{{pay_client}}","description":"Required. Your Snapplify-issued Pay client identifier."},{"key":"secret","value":"{{pay_secret}}","description":"Required. Your Snapplify-issued Pay secret. See auth notes — sent in the query string."}]},"description":"Start a new payment. You POST the payment details to Snapplify Pay; Snapplify returns a `token` and a `redirectUrl`. Redirect the user's browser to `redirectUrl` to complete payment on Snapplify Pay's hosted form. After the gateway completes (success, cancel, or decline), the user is redirected back to the URL(s) you supplied on this request.\n\n### Required\n- `amount` — decimal, in the specified `currency`\n- `currency` — ISO-4217 currency code (e.g. `ZAR`)\n- `country` — ISO-3166 alpha-2 country code (e.g. `ZA`)\n- `redirectUrl` — where to send the user after a **successful** payment\n\n### Optional\n- `referenceCode` — your reference for this payment (echoed back on validate + webhook). Use a stable unique value to reconcile on your side.\n- `notificationUrl` — webhook URL Snapplify will POST the `token` to once the payment completes. See **Payment Completion** in this folder.\n- `declinedUrl` — where to send the user if the payment is declined\n- `cancelUrl` — where to send the user if they cancel at the gateway\n- `backUrl` — where to send the user if they click back on the payment form\n- `description` — free-text shown to the payer\n- `customerId`, `storeId` — optional Snapplify IDs to associate the payment with\n- `allowPartialPayment` — defaults to `false`\n\n### Error codes\n- `100` — invalid client or secret\n- `110` — invalid token, payment, or state"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Invalid client or secret.\",\n  \"code\": 100\n}"}],"_postman_id":"bad36309-69d1-49a9-b46b-a675b0674296"},{"name":"Submit Payment","id":"090e93e4-a723-4245-a018-453b50f0d44b","request":{"method":"GET","header":[],"url":"https://pay.snapplify.com/payment/submit?client={{pay_client}}&token=<token>","description":"<p><strong>This is a browser redirect, not an API call.</strong> Do not fetch this URL from your backend.</p>\n<p>After calling <strong>Begin Payment</strong>, Snapplify returns a <code>redirectUrl</code> pointing at this endpoint. Redirect the user's browser to that URL; Snapplify renders the payment form and handles the rest of the flow (gateway selection, card entry, 3-D Secure, etc.).</p>\n<p>Once the payment completes at the gateway, the user is redirected back to the <code>redirectUrl</code> / <code>declinedUrl</code> / <code>cancelUrl</code> you supplied on the Begin Payment request.</p>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"42bbf2a0-5276-4013-8e23-5ab1e5b4b9dd","id":"42bbf2a0-5276-4013-8e23-5ab1e5b4b9dd","name":"Snapplify Pay","type":"folder"}},"urlObject":{"path":["payment","submit"],"host":["https://pay.snapplify.com"],"query":[{"description":{"content":"<p>Required. Your Pay client identifier.</p>\n","type":"text/plain"},"key":"client","value":"{{pay_client}}"},{"description":{"content":"<p>Required. The <code>token</code> returned by Begin Payment.</p>\n","type":"text/plain"},"key":"token","value":"<token>"}],"variable":[]}},"response":[{"id":"0a2f0739-000b-4d87-8cf1-cf00c2621f38","name":"200 OK — Payment form","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://pay.snapplify.com/payment/submit?client={{pay_client}}&token=<token>","host":["https://pay.snapplify.com"],"path":["payment","submit"],"query":[{"key":"client","value":"{{pay_client}}","description":"Required. Your Pay client identifier."},{"key":"token","value":"<token>","description":"Required. The `token` returned by Begin Payment."}]},"description":"**This is a browser redirect, not an API call.** Do not fetch this URL from your backend.\n\nAfter calling **Begin Payment**, Snapplify returns a `redirectUrl` pointing at this endpoint. Redirect the user's browser to that URL; Snapplify renders the payment form and handles the rest of the flow (gateway selection, card entry, 3-D Secure, etc.).\n\nOnce the payment completes at the gateway, the user is redirected back to the `redirectUrl` / `declinedUrl` / `cancelUrl` you supplied on the Begin Payment request."},"status":"OK","code":200,"_postman_previewlanguage":"html","header":[{"key":"Content-Type","value":"text/html"}],"cookie":[],"responseTime":null,"body":"<!doctype html><html>Payment form rendered in browser</html>"}],"_postman_id":"090e93e4-a723-4245-a018-453b50f0d44b"},{"name":"Validate Payment","id":"8b7bfd54-9fd7-4279-a35b-ec048d2e82b7","request":{"method":"POST","header":[],"url":"https://pay.snapplify.com/payment/validate?client={{pay_client}}&secret={{pay_secret}}&token=<token>","description":"<p>Check the state of a payment by its <code>token</code>. Safe to call at any time — typically called from your backend after your <strong>Payment Completion</strong> webhook fires, or on your post-payment return page, to confirm the payment state before fulfilling the order.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns the full payment record under <code>payment</code>. Key fields:</p>\n<ul>\n<li><code>paymentState</code> — one of <code>PAID</code>, <code>UNPAID</code>, <code>PENDING</code>, <code>ERROR</code>, <code>DECLINED</code></li>\n<li><code>paidAmount</code> — how much was actually captured (may differ from <code>amount</code> if partial)</li>\n<li><code>completedDate</code> — set once the gateway confirms; <code>null</code> otherwise</li>\n<li><code>transactionId</code> — the gateway's transaction reference</li>\n<li><code>gatewayId</code> / <code>gatewayProvider</code> — which gateway processed the payment (e.g. <code>PAYU</code>)</li>\n<li><code>errorMessage</code> / <code>errorCode</code> — gateway error details on decline/failure</li>\n<li><code>validated</code> + <code>validatedDate</code> + <code>validatedToken</code> — set when validation succeeds</li>\n</ul>\n<h3 id=\"error-codes\">Error codes</h3>\n<ul>\n<li><code>100</code> — invalid client or secret</li>\n<li><code>110</code> — invalid token, payment, or state</li>\n</ul>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"42bbf2a0-5276-4013-8e23-5ab1e5b4b9dd","id":"42bbf2a0-5276-4013-8e23-5ab1e5b4b9dd","name":"Snapplify Pay","type":"folder"}},"urlObject":{"path":["payment","validate"],"host":["https://pay.snapplify.com"],"query":[{"description":{"content":"<p>Required.</p>\n","type":"text/plain"},"key":"client","value":"{{pay_client}}"},{"description":{"content":"<p>Required.</p>\n","type":"text/plain"},"key":"secret","value":"{{pay_secret}}"},{"description":{"content":"<p>Required. The <code>token</code> returned by Begin Payment.</p>\n","type":"text/plain"},"key":"token","value":"<token>"}],"variable":[]}},"response":[{"id":"f3311121-2f95-46c3-ac30-0122110779bd","name":"200 OK — Paid","originalRequest":{"method":"POST","header":[],"url":{"raw":"https://pay.snapplify.com/payment/validate?client={{pay_client}}&secret={{pay_secret}}&token=<token>","host":["https://pay.snapplify.com"],"path":["payment","validate"],"query":[{"key":"client","value":"{{pay_client}}","description":"Required."},{"key":"secret","value":"{{pay_secret}}","description":"Required."},{"key":"token","value":"<token>","description":"Required. The `token` returned by Begin Payment."}]},"description":"Check the state of a payment by its `token`. Safe to call at any time — typically called from your backend after your **Payment Completion** webhook fires, or on your post-payment return page, to confirm the payment state before fulfilling the order.\n\n### Response\nReturns the full payment record under `payment`. Key fields:\n\n- `paymentState` — one of `PAID`, `UNPAID`, `PENDING`, `ERROR`, `DECLINED`\n- `paidAmount` — how much was actually captured (may differ from `amount` if partial)\n- `completedDate` — set once the gateway confirms; `null` otherwise\n- `transactionId` — the gateway's transaction reference\n- `gatewayId` / `gatewayProvider` — which gateway processed the payment (e.g. `PAYU`)\n- `errorMessage` / `errorCode` — gateway error details on decline/failure\n- `validated` + `validatedDate` + `validatedToken` — set when validation succeeds\n\n### Error codes\n- `100` — invalid client or secret\n- `110` — invalid token, payment, or state"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"payment\": {\n    \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n    \"updatedDate\": \"2024-06-15T10:35:00.000Z\",\n    \"authorisationCode\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n    \"referenceCode\": \"EXP-ORD-2024-001234\",\n    \"transactionId\": \"txn-payu-8893221\",\n    \"gatewayId\": \"PAYU\",\n    \"gatewayProvider\": \"PAYU\",\n    \"completedDate\": \"2024-06-15T10:34:52.000Z\",\n    \"country\": \"ZA\",\n    \"currency\": \"ZAR\",\n    \"amount\": 199.99,\n    \"paidAmount\": 199.99,\n    \"paymentMethod\": \"CREDIT_CARD\",\n    \"paymentState\": \"PAID\",\n    \"errorMessage\": null,\n    \"errorCode\": null,\n    \"validated\": true,\n    \"validatedDate\": \"2024-06-15T10:35:01.000Z\",\n    \"validatedToken\": \"v-9e3c4f1a-2b5d-4a0c-8f1e-7d3b2a0c9e8f\"\n  }\n}"},{"id":"772b155c-eba1-4ac1-b5bf-a97cba64950c","name":"200 OK — Declined","originalRequest":{"method":"POST","header":[],"url":{"raw":"https://pay.snapplify.com/payment/validate?client={{pay_client}}&secret={{pay_secret}}&token=<token>","host":["https://pay.snapplify.com"],"path":["payment","validate"],"query":[{"key":"client","value":"{{pay_client}}","description":"Required."},{"key":"secret","value":"{{pay_secret}}","description":"Required."},{"key":"token","value":"<token>","description":"Required. The `token` returned by Begin Payment."}]},"description":"Check the state of a payment by its `token`. Safe to call at any time — typically called from your backend after your **Payment Completion** webhook fires, or on your post-payment return page, to confirm the payment state before fulfilling the order.\n\n### Response\nReturns the full payment record under `payment`. Key fields:\n\n- `paymentState` — one of `PAID`, `UNPAID`, `PENDING`, `ERROR`, `DECLINED`\n- `paidAmount` — how much was actually captured (may differ from `amount` if partial)\n- `completedDate` — set once the gateway confirms; `null` otherwise\n- `transactionId` — the gateway's transaction reference\n- `gatewayId` / `gatewayProvider` — which gateway processed the payment (e.g. `PAYU`)\n- `errorMessage` / `errorCode` — gateway error details on decline/failure\n- `validated` + `validatedDate` + `validatedToken` — set when validation succeeds\n\n### Error codes\n- `100` — invalid client or secret\n- `110` — invalid token, payment, or state"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"payment\": {\n    \"createdDate\": \"2024-06-15T10:30:00.000Z\",\n    \"updatedDate\": \"2024-06-15T10:33:00.000Z\",\n    \"authorisationCode\": \"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f\",\n    \"referenceCode\": \"EXP-ORD-2024-001234\",\n    \"transactionId\": null,\n    \"gatewayId\": \"PAYU\",\n    \"gatewayProvider\": \"PAYU\",\n    \"completedDate\": null,\n    \"country\": \"ZA\",\n    \"currency\": \"ZAR\",\n    \"amount\": 199.99,\n    \"paidAmount\": 0.0,\n    \"paymentMethod\": \"CREDIT_CARD\",\n    \"paymentState\": \"DECLINED\",\n    \"errorMessage\": \"Card declined by issuer\",\n    \"errorCode\": \"51\",\n    \"validated\": false,\n    \"validatedDate\": null,\n    \"validatedToken\": null\n  }\n}"},{"id":"d6c3406d-2817-425e-ac5d-8e07464007ce","name":"401 Unauthorized","originalRequest":{"method":"POST","header":[],"url":{"raw":"https://pay.snapplify.com/payment/validate?client={{pay_client}}&secret={{pay_secret}}&token=<token>","host":["https://pay.snapplify.com"],"path":["payment","validate"],"query":[{"key":"client","value":"{{pay_client}}","description":"Required."},{"key":"secret","value":"{{pay_secret}}","description":"Required."},{"key":"token","value":"<token>","description":"Required. The `token` returned by Begin Payment."}]},"description":"Check the state of a payment by its `token`. Safe to call at any time — typically called from your backend after your **Payment Completion** webhook fires, or on your post-payment return page, to confirm the payment state before fulfilling the order.\n\n### Response\nReturns the full payment record under `payment`. Key fields:\n\n- `paymentState` — one of `PAID`, `UNPAID`, `PENDING`, `ERROR`, `DECLINED`\n- `paidAmount` — how much was actually captured (may differ from `amount` if partial)\n- `completedDate` — set once the gateway confirms; `null` otherwise\n- `transactionId` — the gateway's transaction reference\n- `gatewayId` / `gatewayProvider` — which gateway processed the payment (e.g. `PAYU`)\n- `errorMessage` / `errorCode` — gateway error details on decline/failure\n- `validated` + `validatedDate` + `validatedToken` — set when validation succeeds\n\n### Error codes\n- `100` — invalid client or secret\n- `110` — invalid token, payment, or state"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Invalid client or secret.\",\n  \"code\": 100\n}"},{"id":"4c7bfaf4-1465-411c-8d53-08a9a626f561","name":"400 Bad Request — Invalid token","originalRequest":{"method":"POST","header":[],"url":{"raw":"https://pay.snapplify.com/payment/validate?client={{pay_client}}&secret={{pay_secret}}&token=<token>","host":["https://pay.snapplify.com"],"path":["payment","validate"],"query":[{"key":"client","value":"{{pay_client}}","description":"Required."},{"key":"secret","value":"{{pay_secret}}","description":"Required."},{"key":"token","value":"<token>","description":"Required. The `token` returned by Begin Payment."}]},"description":"Check the state of a payment by its `token`. Safe to call at any time — typically called from your backend after your **Payment Completion** webhook fires, or on your post-payment return page, to confirm the payment state before fulfilling the order.\n\n### Response\nReturns the full payment record under `payment`. Key fields:\n\n- `paymentState` — one of `PAID`, `UNPAID`, `PENDING`, `ERROR`, `DECLINED`\n- `paidAmount` — how much was actually captured (may differ from `amount` if partial)\n- `completedDate` — set once the gateway confirms; `null` otherwise\n- `transactionId` — the gateway's transaction reference\n- `gatewayId` / `gatewayProvider` — which gateway processed the payment (e.g. `PAYU`)\n- `errorMessage` / `errorCode` — gateway error details on decline/failure\n- `validated` + `validatedDate` + `validatedToken` — set when validation succeeds\n\n### Error codes\n- `100` — invalid client or secret\n- `110` — invalid token, payment, or state"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"message\": \"Invalid token, payment or state.\",\n  \"code\": 110\n}"}],"_postman_id":"8b7bfd54-9fd7-4279-a35b-ec048d2e82b7"},{"name":"Payment Completion (Webhook)","id":"c93ea95a-45af-450e-8750-3b722c3dc28c","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"body":{"mode":"raw","raw":"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f","options":{"raw":{"language":"text"}}},"url":"{{partner_pay_notification_url}}","description":"<h2 id=\"direction-snapplify-→-your-endpoint\">Direction: Snapplify → YOUR endpoint</h2>\n<p><strong>You implement and host this endpoint.</strong> Snapplify POSTs to the <code>notificationUrl</code> you supplied on <strong>Begin Payment</strong> once the payment reaches a final state (successful, declined, cancelled).</p>\n<h3 id=\"body\">Body</h3>\n<p>The <strong>plain token string</strong> (the same <code>token</code> returned by Begin Payment) — <strong>not JSON</strong>. Despite the <code>Content-Type: application/json; charset=utf-8</code> header, the body is a single UTF-8 string with no quotes and no wrapping object. Read the raw body; do not attempt to JSON-parse it.</p>\n<h3 id=\"expected-response\">Expected response</h3>\n<p>Respond <strong>2xx</strong> quickly to acknowledge receipt. Any other status will result in retry.</p>\n<h3 id=\"recommended-handler-pattern\">Recommended handler pattern</h3>\n<ol>\n<li>Receive the token from Snapplify.</li>\n<li>Respond <code>200 OK</code> immediately (do not block on downstream work).</li>\n<li>Asynchronously call <strong>Validate Payment</strong> with the token to fetch the authoritative payment    state (<code>PAID</code> / <code>DECLINED</code> / etc.) and act on it.</li>\n</ol>\n<p>Do not treat receipt of this webhook as proof of payment — always call Validate Payment to confirm <code>paymentState: PAID</code> and the amount before fulfilling.</p>\n<h3 id=\"registration\">Registration</h3>\n<p>There is no global registration — the target URL is set per-payment via the <code>notificationUrl</code> field on <strong>Begin Payment</strong>. You can use a different URL per payment if needed.</p>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"42bbf2a0-5276-4013-8e23-5ab1e5b4b9dd","id":"42bbf2a0-5276-4013-8e23-5ab1e5b4b9dd","name":"Snapplify Pay","type":"folder"}},"urlObject":{"host":["{{partner_pay_notification_url}}"],"query":[],"variable":[]}},"response":[{"id":"b6b67893-ff94-4f6a-9e06-3f8a228abc3c","name":"200 OK — Acknowledged","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"body":{"mode":"raw","raw":"c8f1e4a2-0b3d-4f8a-9c2e-7d3b1a0c9e8f","options":{"raw":{"language":"text"}}},"url":"{{partner_pay_notification_url}}","description":"## Direction: Snapplify → YOUR endpoint\n\n**You implement and host this endpoint.** Snapplify POSTs to the `notificationUrl` you supplied on **Begin Payment** once the payment reaches a final state (successful, declined, cancelled).\n\n### Body\n\nThe **plain token string** (the same `token` returned by Begin Payment) — **not JSON**. Despite the `Content-Type: application/json; charset=utf-8` header, the body is a single UTF-8 string with no quotes and no wrapping object. Read the raw body; do not attempt to JSON-parse it.\n\n### Expected response\n\nRespond **2xx** quickly to acknowledge receipt. Any other status will result in retry.\n\n### Recommended handler pattern\n\n1. Receive the token from Snapplify.\n2. Respond `200 OK` immediately (do not block on downstream work).\n3. Asynchronously call **Validate Payment** with the token to fetch the authoritative payment    state (`PAID` / `DECLINED` / etc.) and act on it.\n\nDo not treat receipt of this webhook as proof of payment — always call Validate Payment to confirm `paymentState: PAID` and the amount before fulfilling.\n\n### Registration\n\nThere is no global registration — the target URL is set per-payment via the `notificationUrl` field on **Begin Payment**. You can use a different URL per payment if needed."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":""}],"_postman_id":"c93ea95a-45af-450e-8750-3b722c3dc28c"}],"id":"42bbf2a0-5276-4013-8e23-5ab1e5b4b9dd","description":"<p>The <strong>Snapplify Pay API</strong> lets your store take payments through Snapplify's hosted payment form, supporting multiple gateways (PayU, Stripe, Sticitt, etc.) without you handling card details directly.</p>\n<h3 id=\"flow\">Flow</h3>\n<ol>\n<li><strong>Begin Payment</strong> (server→Snapplify) — create a payment and get a <code>token</code> + <code>redirectUrl</code>.</li>\n<li><strong>Submit Payment</strong> (browser redirect) — send the user's browser to the <code>redirectUrl</code>. Snapplify    renders the form, collects card details, talks to the gateway.</li>\n<li><strong>Payment Completion</strong> (webhook: Snapplify→your server) — when the payment reaches a final    state, Snapplify POSTs the <code>token</code> to your registered <code>notificationUrl</code>.</li>\n<li><strong>Validate Payment</strong> (server→Snapplify) — on receipt of the webhook (or on your post-payment    return page), call Validate Payment with the token to fetch the authoritative payment state and    confirm <code>PAID</code> before fulfilling.</li>\n</ol>\n<h3 id=\"authentication\">Authentication</h3>\n<p>Pay uses <strong>query-string credentials</strong> rather than headers: <code>client</code> and <code>secret</code> are passed as query parameters on every server-to-server request. Keep the <code>secret</code> server-side — never embed in browser code or public URLs. Error code <code>100</code> is returned on invalid credentials.</p>\n<h3 id=\"error-codes\">Error codes</h3>\n<ul>\n<li><code>100</code> — invalid client or secret</li>\n<li><code>110</code> — invalid token, payment, or state</li>\n</ul>\n","auth":{"type":"noauth","isInherited":false},"_postman_id":"42bbf2a0-5276-4013-8e23-5ab1e5b4b9dd"},{"name":"Snapplify Catalogue API","item":[{"name":"Push Asset","id":"76677a4b-46a5-4478-bcf8-305d264ec1ed","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"Connection","value":"close"},{"key":"Authorization","value":"Bearer <push_secret>","description":"<p>Optional. Sent only if a push secret was configured for your endpoint during registration. Verify this value matches the secret you provided to Snapplify.</p>\n"}],"body":{"mode":"raw","raw":"{\n  \"id\": 9876543,\n  \"type\": \"asset\",\n  \"availability\": \"AVAILABLE\",\n  \"archived\": false,\n  \"takeDown\": false,\n  \"identifier\": \"9781234567890\",\n  \"relatedIdentifier\": null,\n  \"format\": \"EPUB\",\n  \"drmEnabled\": true,\n  \"title\": \"Example Book Title\",\n  \"subTitle\": null,\n  \"numberOfPages\": 240,\n  \"language\": \"English\",\n  \"edition\": \"1st\",\n  \"description\": \"A short description of the work.\",\n  \"publisher\": \"Example Publisher\",\n  \"subject\": \"Fiction\",\n  \"categories\": [\n    {\n      \"id\": 12,\n      \"label\": \"Fiction\",\n      \"parent\": null\n    }\n  ],\n  \"imageMd5Hash\": \"8d4a3c1b2e9f7a5c6d1e0f8b9c2a3d4e\",\n  \"imageUrlOriginal\": \"https://cdn.snapplify.com/covers/9781234567890.jpg\",\n  \"imageUrl\": \"https://cdn.snapplify.com/covers/9781234567890.jpg\",\n  \"publishedDate\": \"01-06-2024\",\n  \"embargoDate\": null,\n  \"price\": 199.99,\n  \"currency\": \"ZAR\",\n  \"supplier\": {\n    \"label\": \"Example Publisher\",\n    \"code\": \"EXP\"\n  },\n  \"copyright\": \"\\u00a9 2024 Example Publisher\",\n  \"fileSize\": 1245678,\n  \"fileMd5Hash\": \"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6\",\n  \"gradeLevel\": null,\n  \"prescribed\": false,\n  \"bicCode\": \"FA\",\n  \"bisacCode\": \"FIC000000\",\n  \"seriesName\": null,\n  \"seriesNumber\": null,\n  \"includedForSaleInCountries\": \"ZA,NA\",\n  \"excludedForSaleInCountries\": \"\",\n  \"subjects\": [\n    {\n      \"code\": \"Fiction\",\n      \"name\": \"Fiction\"\n    }\n  ],\n  \"drmRestrictions\": [\n    {\n      \"type\": \"COPY\",\n      \"value\": \"10\",\n      \"limited\": true\n    }\n  ],\n  \"contributors\": [\n    {\n      \"firstName\": \"Jane\",\n      \"lastName\": \"Doe\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"{{partner_push_endpoint}}","description":"<h2 id=\"direction-snapplify-→-your-endpoint\">Direction: Snapplify → YOUR endpoint</h2>\n<p><strong>You implement and host this endpoint.</strong> Snapplify POSTs an asset payload to the URL you registered with us. You do not call this endpoint — Snapplify calls it.</p>\n<p>Used to keep your catalogue in sync with Snapplify's: every time an asset becomes available in a store you sell, becomes unavailable, or has its metadata updated, Snapplify will POST the current state of that asset to your endpoint.</p>\n<h3 id=\"registration\">Registration</h3>\n<p>Provide your endpoint URL (and optionally a bearer token / push secret) to Snapplify during onboarding. Both are stored against your account; you cannot register them yourself via the API.</p>\n<h3 id=\"authentication\">Authentication</h3>\n<p>If you supplied a push secret, Snapplify includes it in the <code>Authorization: Bearer &lt;push_secret&gt;</code> header. Compare against the secret you provided. If you did not supply a push secret, no <code>Authorization</code> header is sent — in that case you should restrict access by IP allowlist or another transport-level control.</p>\n<h3 id=\"expected-response\">Expected response</h3>\n<ul>\n<li><strong>2xx</strong> — Snapplify treats the message as delivered and removes it from the outbound queue.</li>\n<li><strong>Anything else</strong> (4xx, 5xx, network failure, timeout) — Snapplify treats the message as a   failure, increments your endpoint's error counter, and returns the message to the queue for   redelivery.</li>\n</ul>\n<h3 id=\"retry-behaviour\">Retry behaviour</h3>\n<p>Failed deliveries are retried automatically. Snapplify does <strong>not</strong> distinguish between 4xx and 5xx — both are treated as transient and retried. If your endpoint cannot process a particular asset (e.g. malformed for your system), you should still respond <code>2xx</code> to ack the delivery and log/alert internally; otherwise Snapplify will keep redelivering until your endpoint is marked unhealthy.</p>\n<h3 id=\"health-threshold\">Health threshold</h3>\n<p>If your endpoint accumulates too many errors within a configured time window, Snapplify marks it unhealthy and stops sending. Re-enabling requires Snapplify-side intervention. The exact thresholds are configured per partner; contact Snapplify if you need them adjusted for a planned outage.</p>\n<h3 id=\"timeouts\">Timeouts</h3>\n<ul>\n<li>Connection: <strong>10 seconds</strong></li>\n<li>Read: <strong>30 seconds</strong></li>\n</ul>\n<p>Plan your handler accordingly. If your processing takes longer than 30 seconds, ack quickly and process asynchronously.</p>\n<h3 id=\"rate-limits\">Rate limits</h3>\n<p>Per-partner rate limits are configured during onboarding (<code>maxRequestsPerSecond</code>, <code>maxRequestsPerHost</code>, <code>maxConcurrentRequests</code>). Snapplify will not exceed these. If your endpoint can handle more (or needs less), contact us.</p>\n<h3 id=\"idempotency\">Idempotency</h3>\n<p>There is no per-request idempotency key in the headers. Use the body's <code>id</code> (the StoreAsset id) plus <code>identifier</code> (ISBN/SKU) to dedupe. Snapplify may resend the same asset multiple times — your endpoint must be idempotent.</p>\n<h3 id=\"ordering\">Ordering</h3>\n<p>Deliveries to your endpoint preserve order: a later state of an asset will not be delivered before an earlier state. If a delivery fails and is retried, that retry blocks subsequent deliveries for your endpoint until it succeeds (or you are marked unhealthy).</p>\n<h3 id=\"key-body-fields\">Key body fields</h3>\n<ul>\n<li><code>id</code> — Snapplify StoreAsset ID (stable; use for deduplication)</li>\n<li><code>identifier</code> — primary identifier (ISBN, SKU)</li>\n<li><code>availability</code> — <code>AVAILABLE</code> or <code>UNAVAILABLE</code>. <code>UNAVAILABLE</code> means the asset has been   archived, taken down, or removed from the store — treat as a soft delete</li>\n<li><code>archived</code> / <code>takeDown</code> — boolean flags backing the <code>availability</code> field</li>\n<li><code>format</code> — file format (e.g. <code>EPUB</code>, <code>PDF</code>)</li>\n<li><code>drmEnabled</code> + <code>drmRestrictions[]</code> — DRM controls applicable to the asset</li>\n<li><code>price</code> + <code>currency</code> — current price in the store's currency</li>\n<li><code>includedForSaleInCountries</code> / <code>excludedForSaleInCountries</code> — comma-separated ISO country codes</li>\n<li><code>imageUrl</code> / <code>imageUrlOriginal</code> — currently identical (legacy duplication; prefer <code>imageUrl</code>)</li>\n<li>Date fields use <code>dd-MM-yyyy</code> format</li>\n</ul>\n","auth":{"type":"noauth","isInherited":true,"source":{"_postman_id":"0e3a1013-7701-43c9-bdd2-d1c500005253","id":"0e3a1013-7701-43c9-bdd2-d1c500005253","name":"Snapplify Catalogue API","type":"folder"}},"urlObject":{"host":["{{partner_push_endpoint}}"],"query":[],"variable":[]}},"response":[{"id":"7eb437ca-c062-415e-bcba-5cdcc0c82ceb","name":"200 OK — Acknowledged","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"Connection","value":"close"},{"key":"Authorization","value":"Bearer <push_secret>","description":"Optional. Sent only if a push secret was configured for your endpoint during registration. Verify this value matches the secret you provided to Snapplify."}],"body":{"mode":"raw","raw":"{\n  \"id\": 9876543,\n  \"type\": \"asset\",\n  \"availability\": \"AVAILABLE\",\n  \"archived\": false,\n  \"takeDown\": false,\n  \"identifier\": \"9781234567890\",\n  \"relatedIdentifier\": null,\n  \"format\": \"EPUB\",\n  \"drmEnabled\": true,\n  \"title\": \"Example Book Title\",\n  \"subTitle\": null,\n  \"numberOfPages\": 240,\n  \"language\": \"English\",\n  \"edition\": \"1st\",\n  \"description\": \"A short description of the work.\",\n  \"publisher\": \"Example Publisher\",\n  \"subject\": \"Fiction\",\n  \"categories\": [\n    {\n      \"id\": 12,\n      \"label\": \"Fiction\",\n      \"parent\": null\n    }\n  ],\n  \"imageMd5Hash\": \"8d4a3c1b2e9f7a5c6d1e0f8b9c2a3d4e\",\n  \"imageUrlOriginal\": \"https://cdn.snapplify.com/covers/9781234567890.jpg\",\n  \"imageUrl\": \"https://cdn.snapplify.com/covers/9781234567890.jpg\",\n  \"publishedDate\": \"01-06-2024\",\n  \"embargoDate\": null,\n  \"price\": 199.99,\n  \"currency\": \"ZAR\",\n  \"supplier\": {\n    \"label\": \"Example Publisher\",\n    \"code\": \"EXP\"\n  },\n  \"copyright\": \"\\u00a9 2024 Example Publisher\",\n  \"fileSize\": 1245678,\n  \"fileMd5Hash\": \"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6\",\n  \"gradeLevel\": null,\n  \"prescribed\": false,\n  \"bicCode\": \"FA\",\n  \"bisacCode\": \"FIC000000\",\n  \"seriesName\": null,\n  \"seriesNumber\": null,\n  \"includedForSaleInCountries\": \"ZA,NA\",\n  \"excludedForSaleInCountries\": \"\",\n  \"subjects\": [\n    {\n      \"code\": \"Fiction\",\n      \"name\": \"Fiction\"\n    }\n  ],\n  \"drmRestrictions\": [\n    {\n      \"type\": \"COPY\",\n      \"value\": \"10\",\n      \"limited\": true\n    }\n  ],\n  \"contributors\": [\n    {\n      \"firstName\": \"Jane\",\n      \"lastName\": \"Doe\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"{{partner_push_endpoint}}","description":"## Direction: Snapplify → YOUR endpoint\n\n**You implement and host this endpoint.** Snapplify POSTs an asset payload to the URL you registered with us. You do not call this endpoint — Snapplify calls it.\n\nUsed to keep your catalogue in sync with Snapplify's: every time an asset becomes available in a store you sell, becomes unavailable, or has its metadata updated, Snapplify will POST the current state of that asset to your endpoint.\n\n### Registration\n\nProvide your endpoint URL (and optionally a bearer token / push secret) to Snapplify during onboarding. Both are stored against your account; you cannot register them yourself via the API.\n\n### Authentication\n\nIf you supplied a push secret, Snapplify includes it in the `Authorization: Bearer <push_secret>` header. Compare against the secret you provided. If you did not supply a push secret, no `Authorization` header is sent — in that case you should restrict access by IP allowlist or another transport-level control.\n\n### Expected response\n\n- **2xx** — Snapplify treats the message as delivered and removes it from the outbound queue.\n- **Anything else** (4xx, 5xx, network failure, timeout) — Snapplify treats the message as a   failure, increments your endpoint's error counter, and returns the message to the queue for   redelivery.\n\n### Retry behaviour\n\nFailed deliveries are retried automatically. Snapplify does **not** distinguish between 4xx and 5xx — both are treated as transient and retried. If your endpoint cannot process a particular asset (e.g. malformed for your system), you should still respond `2xx` to ack the delivery and log/alert internally; otherwise Snapplify will keep redelivering until your endpoint is marked unhealthy.\n\n### Health threshold\n\nIf your endpoint accumulates too many errors within a configured time window, Snapplify marks it unhealthy and stops sending. Re-enabling requires Snapplify-side intervention. The exact thresholds are configured per partner; contact Snapplify if you need them adjusted for a planned outage.\n\n### Timeouts\n\n- Connection: **10 seconds**\n- Read: **30 seconds**\n\nPlan your handler accordingly. If your processing takes longer than 30 seconds, ack quickly and process asynchronously.\n\n### Rate limits\n\nPer-partner rate limits are configured during onboarding (`maxRequestsPerSecond`, `maxRequestsPerHost`, `maxConcurrentRequests`). Snapplify will not exceed these. If your endpoint can handle more (or needs less), contact us.\n\n### Idempotency\n\nThere is no per-request idempotency key in the headers. Use the body's `id` (the StoreAsset id) plus `identifier` (ISBN/SKU) to dedupe. Snapplify may resend the same asset multiple times — your endpoint must be idempotent.\n\n### Ordering\n\nDeliveries to your endpoint preserve order: a later state of an asset will not be delivered before an earlier state. If a delivery fails and is retried, that retry blocks subsequent deliveries for your endpoint until it succeeds (or you are marked unhealthy).\n\n### Key body fields\n\n- `id` — Snapplify StoreAsset ID (stable; use for deduplication)\n- `identifier` — primary identifier (ISBN, SKU)\n- `availability` — `AVAILABLE` or `UNAVAILABLE`. `UNAVAILABLE` means the asset has been   archived, taken down, or removed from the store — treat as a soft delete\n- `archived` / `takeDown` — boolean flags backing the `availability` field\n- `format` — file format (e.g. `EPUB`, `PDF`)\n- `drmEnabled` + `drmRestrictions[]` — DRM controls applicable to the asset\n- `price` + `currency` — current price in the store's currency\n- `includedForSaleInCountries` / `excludedForSaleInCountries` — comma-separated ISO country codes\n- `imageUrl` / `imageUrlOriginal` — currently identical (legacy duplication; prefer `imageUrl`)\n- Date fields use `dd-MM-yyyy` format"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ok\"\n}"},{"id":"b3f794dc-8848-476c-bff5-aa794c1b07f5","name":"204 No Content — Acknowledged","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"Connection","value":"close"},{"key":"Authorization","value":"Bearer <push_secret>","description":"Optional. Sent only if a push secret was configured for your endpoint during registration. Verify this value matches the secret you provided to Snapplify."}],"body":{"mode":"raw","raw":"{\n  \"id\": 9876543,\n  \"type\": \"asset\",\n  \"availability\": \"AVAILABLE\",\n  \"archived\": false,\n  \"takeDown\": false,\n  \"identifier\": \"9781234567890\",\n  \"relatedIdentifier\": null,\n  \"format\": \"EPUB\",\n  \"drmEnabled\": true,\n  \"title\": \"Example Book Title\",\n  \"subTitle\": null,\n  \"numberOfPages\": 240,\n  \"language\": \"English\",\n  \"edition\": \"1st\",\n  \"description\": \"A short description of the work.\",\n  \"publisher\": \"Example Publisher\",\n  \"subject\": \"Fiction\",\n  \"categories\": [\n    {\n      \"id\": 12,\n      \"label\": \"Fiction\",\n      \"parent\": null\n    }\n  ],\n  \"imageMd5Hash\": \"8d4a3c1b2e9f7a5c6d1e0f8b9c2a3d4e\",\n  \"imageUrlOriginal\": \"https://cdn.snapplify.com/covers/9781234567890.jpg\",\n  \"imageUrl\": \"https://cdn.snapplify.com/covers/9781234567890.jpg\",\n  \"publishedDate\": \"01-06-2024\",\n  \"embargoDate\": null,\n  \"price\": 199.99,\n  \"currency\": \"ZAR\",\n  \"supplier\": {\n    \"label\": \"Example Publisher\",\n    \"code\": \"EXP\"\n  },\n  \"copyright\": \"\\u00a9 2024 Example Publisher\",\n  \"fileSize\": 1245678,\n  \"fileMd5Hash\": \"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6\",\n  \"gradeLevel\": null,\n  \"prescribed\": false,\n  \"bicCode\": \"FA\",\n  \"bisacCode\": \"FIC000000\",\n  \"seriesName\": null,\n  \"seriesNumber\": null,\n  \"includedForSaleInCountries\": \"ZA,NA\",\n  \"excludedForSaleInCountries\": \"\",\n  \"subjects\": [\n    {\n      \"code\": \"Fiction\",\n      \"name\": \"Fiction\"\n    }\n  ],\n  \"drmRestrictions\": [\n    {\n      \"type\": \"COPY\",\n      \"value\": \"10\",\n      \"limited\": true\n    }\n  ],\n  \"contributors\": [\n    {\n      \"firstName\": \"Jane\",\n      \"lastName\": \"Doe\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"{{partner_push_endpoint}}","description":"## Direction: Snapplify → YOUR endpoint\n\n**You implement and host this endpoint.** Snapplify POSTs an asset payload to the URL you registered with us. You do not call this endpoint — Snapplify calls it.\n\nUsed to keep your catalogue in sync with Snapplify's: every time an asset becomes available in a store you sell, becomes unavailable, or has its metadata updated, Snapplify will POST the current state of that asset to your endpoint.\n\n### Registration\n\nProvide your endpoint URL (and optionally a bearer token / push secret) to Snapplify during onboarding. Both are stored against your account; you cannot register them yourself via the API.\n\n### Authentication\n\nIf you supplied a push secret, Snapplify includes it in the `Authorization: Bearer <push_secret>` header. Compare against the secret you provided. If you did not supply a push secret, no `Authorization` header is sent — in that case you should restrict access by IP allowlist or another transport-level control.\n\n### Expected response\n\n- **2xx** — Snapplify treats the message as delivered and removes it from the outbound queue.\n- **Anything else** (4xx, 5xx, network failure, timeout) — Snapplify treats the message as a   failure, increments your endpoint's error counter, and returns the message to the queue for   redelivery.\n\n### Retry behaviour\n\nFailed deliveries are retried automatically. Snapplify does **not** distinguish between 4xx and 5xx — both are treated as transient and retried. If your endpoint cannot process a particular asset (e.g. malformed for your system), you should still respond `2xx` to ack the delivery and log/alert internally; otherwise Snapplify will keep redelivering until your endpoint is marked unhealthy.\n\n### Health threshold\n\nIf your endpoint accumulates too many errors within a configured time window, Snapplify marks it unhealthy and stops sending. Re-enabling requires Snapplify-side intervention. The exact thresholds are configured per partner; contact Snapplify if you need them adjusted for a planned outage.\n\n### Timeouts\n\n- Connection: **10 seconds**\n- Read: **30 seconds**\n\nPlan your handler accordingly. If your processing takes longer than 30 seconds, ack quickly and process asynchronously.\n\n### Rate limits\n\nPer-partner rate limits are configured during onboarding (`maxRequestsPerSecond`, `maxRequestsPerHost`, `maxConcurrentRequests`). Snapplify will not exceed these. If your endpoint can handle more (or needs less), contact us.\n\n### Idempotency\n\nThere is no per-request idempotency key in the headers. Use the body's `id` (the StoreAsset id) plus `identifier` (ISBN/SKU) to dedupe. Snapplify may resend the same asset multiple times — your endpoint must be idempotent.\n\n### Ordering\n\nDeliveries to your endpoint preserve order: a later state of an asset will not be delivered before an earlier state. If a delivery fails and is retried, that retry blocks subsequent deliveries for your endpoint until it succeeds (or you are marked unhealthy).\n\n### Key body fields\n\n- `id` — Snapplify StoreAsset ID (stable; use for deduplication)\n- `identifier` — primary identifier (ISBN, SKU)\n- `availability` — `AVAILABLE` or `UNAVAILABLE`. `UNAVAILABLE` means the asset has been   archived, taken down, or removed from the store — treat as a soft delete\n- `archived` / `takeDown` — boolean flags backing the `availability` field\n- `format` — file format (e.g. `EPUB`, `PDF`)\n- `drmEnabled` + `drmRestrictions[]` — DRM controls applicable to the asset\n- `price` + `currency` — current price in the store's currency\n- `includedForSaleInCountries` / `excludedForSaleInCountries` — comma-separated ISO country codes\n- `imageUrl` / `imageUrlOriginal` — currently identical (legacy duplication; prefer `imageUrl`)\n- Date fields use `dd-MM-yyyy` format"},"status":"No Content","code":204,"_postman_previewlanguage":"text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":""},{"id":"2deacd74-bbc6-4a6c-8bb0-06d440771252","name":"5xx — Will be retried","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"Connection","value":"close"},{"key":"Authorization","value":"Bearer <push_secret>","description":"Optional. Sent only if a push secret was configured for your endpoint during registration. Verify this value matches the secret you provided to Snapplify."}],"body":{"mode":"raw","raw":"{\n  \"id\": 9876543,\n  \"type\": \"asset\",\n  \"availability\": \"AVAILABLE\",\n  \"archived\": false,\n  \"takeDown\": false,\n  \"identifier\": \"9781234567890\",\n  \"relatedIdentifier\": null,\n  \"format\": \"EPUB\",\n  \"drmEnabled\": true,\n  \"title\": \"Example Book Title\",\n  \"subTitle\": null,\n  \"numberOfPages\": 240,\n  \"language\": \"English\",\n  \"edition\": \"1st\",\n  \"description\": \"A short description of the work.\",\n  \"publisher\": \"Example Publisher\",\n  \"subject\": \"Fiction\",\n  \"categories\": [\n    {\n      \"id\": 12,\n      \"label\": \"Fiction\",\n      \"parent\": null\n    }\n  ],\n  \"imageMd5Hash\": \"8d4a3c1b2e9f7a5c6d1e0f8b9c2a3d4e\",\n  \"imageUrlOriginal\": \"https://cdn.snapplify.com/covers/9781234567890.jpg\",\n  \"imageUrl\": \"https://cdn.snapplify.com/covers/9781234567890.jpg\",\n  \"publishedDate\": \"01-06-2024\",\n  \"embargoDate\": null,\n  \"price\": 199.99,\n  \"currency\": \"ZAR\",\n  \"supplier\": {\n    \"label\": \"Example Publisher\",\n    \"code\": \"EXP\"\n  },\n  \"copyright\": \"\\u00a9 2024 Example Publisher\",\n  \"fileSize\": 1245678,\n  \"fileMd5Hash\": \"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6\",\n  \"gradeLevel\": null,\n  \"prescribed\": false,\n  \"bicCode\": \"FA\",\n  \"bisacCode\": \"FIC000000\",\n  \"seriesName\": null,\n  \"seriesNumber\": null,\n  \"includedForSaleInCountries\": \"ZA,NA\",\n  \"excludedForSaleInCountries\": \"\",\n  \"subjects\": [\n    {\n      \"code\": \"Fiction\",\n      \"name\": \"Fiction\"\n    }\n  ],\n  \"drmRestrictions\": [\n    {\n      \"type\": \"COPY\",\n      \"value\": \"10\",\n      \"limited\": true\n    }\n  ],\n  \"contributors\": [\n    {\n      \"firstName\": \"Jane\",\n      \"lastName\": \"Doe\"\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"{{partner_push_endpoint}}","description":"## Direction: Snapplify → YOUR endpoint\n\n**You implement and host this endpoint.** Snapplify POSTs an asset payload to the URL you registered with us. You do not call this endpoint — Snapplify calls it.\n\nUsed to keep your catalogue in sync with Snapplify's: every time an asset becomes available in a store you sell, becomes unavailable, or has its metadata updated, Snapplify will POST the current state of that asset to your endpoint.\n\n### Registration\n\nProvide your endpoint URL (and optionally a bearer token / push secret) to Snapplify during onboarding. Both are stored against your account; you cannot register them yourself via the API.\n\n### Authentication\n\nIf you supplied a push secret, Snapplify includes it in the `Authorization: Bearer <push_secret>` header. Compare against the secret you provided. If you did not supply a push secret, no `Authorization` header is sent — in that case you should restrict access by IP allowlist or another transport-level control.\n\n### Expected response\n\n- **2xx** — Snapplify treats the message as delivered and removes it from the outbound queue.\n- **Anything else** (4xx, 5xx, network failure, timeout) — Snapplify treats the message as a   failure, increments your endpoint's error counter, and returns the message to the queue for   redelivery.\n\n### Retry behaviour\n\nFailed deliveries are retried automatically. Snapplify does **not** distinguish between 4xx and 5xx — both are treated as transient and retried. If your endpoint cannot process a particular asset (e.g. malformed for your system), you should still respond `2xx` to ack the delivery and log/alert internally; otherwise Snapplify will keep redelivering until your endpoint is marked unhealthy.\n\n### Health threshold\n\nIf your endpoint accumulates too many errors within a configured time window, Snapplify marks it unhealthy and stops sending. Re-enabling requires Snapplify-side intervention. The exact thresholds are configured per partner; contact Snapplify if you need them adjusted for a planned outage.\n\n### Timeouts\n\n- Connection: **10 seconds**\n- Read: **30 seconds**\n\nPlan your handler accordingly. If your processing takes longer than 30 seconds, ack quickly and process asynchronously.\n\n### Rate limits\n\nPer-partner rate limits are configured during onboarding (`maxRequestsPerSecond`, `maxRequestsPerHost`, `maxConcurrentRequests`). Snapplify will not exceed these. If your endpoint can handle more (or needs less), contact us.\n\n### Idempotency\n\nThere is no per-request idempotency key in the headers. Use the body's `id` (the StoreAsset id) plus `identifier` (ISBN/SKU) to dedupe. Snapplify may resend the same asset multiple times — your endpoint must be idempotent.\n\n### Ordering\n\nDeliveries to your endpoint preserve order: a later state of an asset will not be delivered before an earlier state. If a delivery fails and is retried, that retry blocks subsequent deliveries for your endpoint until it succeeds (or you are marked unhealthy).\n\n### Key body fields\n\n- `id` — Snapplify StoreAsset ID (stable; use for deduplication)\n- `identifier` — primary identifier (ISBN, SKU)\n- `availability` — `AVAILABLE` or `UNAVAILABLE`. `UNAVAILABLE` means the asset has been   archived, taken down, or removed from the store — treat as a soft delete\n- `archived` / `takeDown` — boolean flags backing the `availability` field\n- `format` — file format (e.g. `EPUB`, `PDF`)\n- `drmEnabled` + `drmRestrictions[]` — DRM controls applicable to the asset\n- `price` + `currency` — current price in the store's currency\n- `includedForSaleInCountries` / `excludedForSaleInCountries` — comma-separated ISO country codes\n- `imageUrl` / `imageUrlOriginal` — currently identical (legacy duplication; prefer `imageUrl`)\n- Date fields use `dd-MM-yyyy` format"},"status":"Internal Server Error","code":500,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": \"temporary processing failure\"\n}"}],"_postman_id":"76677a4b-46a5-4478-bcf8-305d264ec1ed"}],"id":"0e3a1013-7701-43c9-bdd2-d1c500005253","description":"<p>The <strong>Snapplify Catalogue API</strong> keeps your catalogue in sync with Snapplify's by pushing asset metadata to your infrastructure as it changes.</p>\n<p><strong>Direction:</strong> Snapplify → your endpoint. You implement and host the endpoints in this folder; Snapplify calls into them.</p>\n<h3 id=\"how-it-works\">How it works</h3>\n<ul>\n<li>You provide Snapplify with a URL (and optional bearer secret) during onboarding.</li>\n<li>Snapplify POSTs JSON to that URL when relevant catalogue events occur (asset added to a store,   metadata changed, asset taken down, etc.).</li>\n<li>You respond with <strong>2xx</strong> to acknowledge. Anything else is treated as a failure and triggers retry.</li>\n<li>Repeated failures will mark your endpoint unhealthy and stop deliveries until manually re-enabled.</li>\n</ul>\n<h3 id=\"common-defaults-across-all-endpoints\">Common defaults across all endpoints</h3>\n<ul>\n<li>Connection timeout: <strong>10 seconds</strong></li>\n<li>Read timeout: <strong>30 seconds</strong></li>\n<li>No request-id header — your endpoint must dedupe using IDs from the body</li>\n<li>Order is preserved per partner; a failed delivery blocks subsequent deliveries until it succeeds   or your endpoint is marked unhealthy</li>\n</ul>\n","auth":{"type":"noauth","isInherited":false},"_postman_id":"0e3a1013-7701-43c9-bdd2-d1c500005253"}],"auth":{"type":"apikey","apikey":{"basicConfig":[{"key":"key","value":"apiKey"},{"key":"value","value":"{{api_key}}"}]}},"event":[{"listen":"prerequest","script":{"id":"84e88fd9-022c-4892-be82-b8fba4f642f3","type":"text/javascript","packages":{},"exec":[""]}},{"listen":"test","script":{"id":"07b4179c-4649-42d0-98d5-5c83fd9d32a3","type":"text/javascript","packages":{},"exec":[""]}}],"variable":[{"key":"baseUrl","value":"https://api.snapplify.com","type":"string"},{"key":"authUrl","value":"https://auth.snapplify.com","type":"string"},{"key":"payUrl","value":"https://pay.snapplify.com","type":"string"}]}