Postman
The Offer API ships a Postman collection with a request for every route. Import it, run the Quickstart folder, and every other request has an app, keys and ids to work with.
Download
- Collection (
offer-api.postman_collection.json): every route in folders by resource, with example bodies, the right key per request, and scripts that save ids and keys as you go. It points at the local API by default. - Environment (
offer-api.postman_environment.json): only needed for a deployed API. It overridesbaseUrlandadminKey.
Both files live in api/postman/ in the repo. Postman's Import also accepts the download links as a URL.
Get started
Import the collection
In Postman, choose Import and drop in
offer-api.postman_collection.json. It shows up as Offer API.Point it at your API
For a local API (
pnpm dev:api) there is nothing to set:baseUrlstarts ashttp://localhost:6767andadminKeyas the localdev-admin-key.For a deployed API, import
offer-api.postman_environment.json, select Offer API (deployed) in the environment menu, and setbaseUrlto your API's URL andadminKeyto itsADMIN_API_KEY. Quickstart creates its app with the admin key, so it needs both.Run Quickstart
Open the Quickstart folder and send its requests in order, or press Run on the folder to send them all. Create an app uses the admin key and saves the new app's id, secret key and publishable key into the collection variables. The rest creates a
postsentitlement, a Free plan with 3 posts and a Pro plan with 100, an account calleduser_42, one recorded post, and an upgrade to Pro.Use the other folders
Every other request now has an app and data to act on. Requests that create something save its id, so the next request in the folder uses it.
appId, secretKey and publicKey in the collection's Variables tab. The keys are under Developers → API keys in the dashboard.Folders
- Quickstart
- Creates an app and a small catalog, then reads and changes an account. Run it first.
- Service
- Health check, the OpenAPI document, the reference page and the webhook event catalog. No key.
- Apps
- Read and update the app, and rotate its keys. Rotating saves the new key.
- Entitlements, Add-ons, Incentives, Plans
- The catalog: create, read and update records, and attach entitlements and add-ons to plans and incentives.
- Accounts, Usage
- Search and change accounts, mint account tokens, read access, and move usage counters.
- Offers, Checkouts, Subscriptions, PayPal
- Selling through PayPal. These need a PayPal sandbox connection: set
paypalClientIdandpaypalClientSecret, then send PayPal → Connect PayPal. - Cancel flows, Cancel sessions
- Create a flow from the template, preview its save offer, and walk a session through it with an account token.
- Analytics, Webhooks and events
- Usage reports, webhook endpoints, test sends, delivery logs and the event log.
- MCP server
- Calls the app's MCP server with the secret key: initialize, list and call tools, read a resource, get a prompt. Also the dashboard's settings, connections and call log routes, with the admin key.
- MCP OAuth
- The sign-in an MCP client goes through: discovery, client registration, authorize, approval, the PKCE code exchange, a tool list with the access token, refresh and deny. The admin-key approval stands in for the dashboard's consent page.
- Admin
- Workspaces, history import, pauses and agent threads. These use the admin key.
- Clean up
- Deletes what the other folders created, ending with the app. Run it last, or skip it to keep the data.
Keys
The collection sends the app's secret key by default. Requests that a browser or another service would make send a different key, set on their Authorization tab:
| Variable | Key | Used by |
|---|---|---|
| secretKey | key_… | Every request that doesn't say otherwise. |
| publicKey | pub_… | Browser routes: plan reads, usage, pricing, public offers and checkouts. |
| accountToken | act_… | Cancel sessions. Send Accounts → Mint an account token first; tokens last an hour. |
| adminKey | ADMIN_API_KEY | The Admin folder, the MCP dashboard and approval routes, and some of Clean up. |
| mcpAccessToken | mcp_at_… | The MCP server, as an OAuth client. Saved by MCP OAuth → Exchange the code; lasts an hour. |
Each request's description says which other keys it accepts. Authentication explains what each key can do.
secretKey, publicKey, accountToken, mcpAccessToken, mcpRefreshToken and adminKey before you export or share the collection.Variables
| Variable | Starts as | Set by |
|---|---|---|
baseUrl | http://localhost:6767 | You, or the environment. |
adminKey | dev-admin-key | You, or the environment. |
appId, secretKey, publicKey | Empty | Quickstart → Create an app. |
accountId | user_42 | You. The account most requests act on. |
freePlanId, planId | free, pro | You. |
entitlementId, addonId, incentiveId | posts, priority_support, launch_boost | You. |
offerId, flowId | launch, default | You. Creating the cancel flow saves its id. |
checkoutId, sessionId, reportId, webhookId, deliveryId | Empty | The request that creates each one. |
accountToken | Empty | Accounts → Mint an account token. |
webhookUrl | https://example.com/offer-webhooks | You. Point it at a receiver you can watch, such as webhook.site. |
paypalClientId, paypalClientSecret | Empty | You, from a PayPal sandbox REST app. |
orgId, userId, threadId | postman_workspace, postman_user, postman_thread | You. Used by the Admin and MCP OAuth folders. |
mcpSessionId, mcpConnectionId | Empty | The MCP server folder. |
oauthRedirectUri, oauthCodeVerifier, oauthCodeChallenge | A local callback and a fixed PKCE pair | You. The MCP OAuth folder uses them as is. |
oauthClientId, oauthRequestId, oauthCode | Empty | The MCP OAuth folder, one step at a time. |
mcpAccessToken, mcpRefreshToken | Empty | The MCP OAuth folder's token requests. |
Run the whole collection
The folders are ordered so the collection runs top to bottom: Quickstart sets up, the resource folders build on it, and Clean up removes everything. Use Run on the collection in Postman, or Newman, Postman's command-line runner:
npx newman run api/postman/offer-api.postman_collection.jsonEvery request carries one test: no 5xx. Some requests answer 404 or 409 on purpose in a full run. Requests that create a record Quickstart already made return 409, and without PayPal connected, publishing, checkouts, subscriptions and save offers return 409 too.
Keep it in step with the API
The collection is generated. Requests are defined in api/postman/requests.ts, and the generator reads the API's own route table, so it refuses to build if a route has no request or a request has no route.
cd api
bun run postman
# or, with the API running in Docker
docker compose exec api bun run postmanapi/test/postman.test.ts runs the same check in the API's test suite, and also fails when the committed JSON is out of date. Adding a route without a Postman request fails the tests.