Build your purchase flow.

Choose who runs the purchase backend, describe what your users should experience, and review a running app.

If the pieces are still unfamiliar, follow Alice’s purchase first. You do not need to learn the API names to decide what your product should do.

1. Choose your services#

For an existing app, keep your login and paywall. Choose who will verify purchases and maintain access.

Use a managed service

IAPKit runs purchase verification, subscription records, and event delivery. Your backend calls it to authorize your users.

Building a paywall or data service instead? Choose the part your business owns; you do not need to build the whole purchase backend.

The contract stays; the backend can differ

Run the flow locally

openiap-commerce-protocol-example

A small Fetch handler looks up each request in the published HTTP manifest, validates it, and calls a JavaScript handler backed by SQLite. It implements all six REST operations.

Read code: fetch
See the service implementation

IAPKit

Hono registers the same manifest’s routes and sends validated input to shared handlers backed by Convex and store services. It implements all six operations and also exposes GraphQL.

Read code: HTTP_BINDING route registration
How to check this behavior

Example. The dashboard calls real local HTTP endpoints, validates their responses, and checks the purchase flow. Run npm test. Inspect reference

IAPKit. The portable runner drives real route code with substituted store/database I/O and compares both bindings. Inspect reference

Follow the same verification, ownership, and access steps in both projects. A provider switch also needs compatible capabilities, credentials, store evidence, and a plan for purchase history; the composition checks show what has been exercised locally.

2. Give AI the brief#

Open the brief, copy it into your coding agent, and fill in your product and service choices. The agent can inspect your existing stack. For example: “Add Premium subscriptions to my app. Use IAPKit for verification and access; keep my existing login and paywall.”

Open the brief to copy
Integrate OpenIAP Commerce Protocol into this project.
Product and desired behavior: [what users should be able to do].
Store and product type: [Apple, Google Play, Amazon, or Meta Horizon]; [subscription, durable purchase, or consumable].
Services to use or own: [name them, or ask me to choose].

Implementation references:
- Runnable teaching backend: https://github.com/hyodotdev/openiap-commerce-protocol-example
- IAPKit service source: https://github.com/hyodotdev/openiap/tree/main/packages/kit
- Step-by-step comparison: https://openiap.dev/commerce-protocol/getting-started
Read the example's INTEGRATE.md for my role; follow BUILD.md for a commerce backend. Compare each responsibility with IAPKit's corresponding handler and tests. The example uses fictional purchases and all six REST operations, including erasure; IAPKit also shows store integrations and GraphQL. Use the contract as the authority, not either implementation's shortcuts.
Check the chosen store and product type before implementing. IAPKit's Apple/Google subscription path uses subscription state and lifecycle events. Its Amazon/Horizon ownership path rechecks saved evidence on entitlements reads; use productIds, not subscription expiry or invented events. Authenticate the store account link on the app backend. Keep consumable quantities in a separate durable fulfillment ledger.
Inspect this project's instructions and stack. Install openiap-commerce-protocol; use its SPEC.md, generated bindings/schemas, and conformance tools as the contract.

Implement the connection using existing project patterns. Start with a runnable local result. For a provider, complete every selected profile, including account erasure and event delivery; advertise only completed profiles and bindings. Run the applicable conformance and product checks. Fix every failure and rerun; a test that expects a known failure does not complete the implementation. Repeat installation, tests, and startup from a clean source-only copy.
Show the running URL and user-visible outcomes, with source and verification commands for future changes. Separate fixture evidence from real store/deployment checks; list remaining work and product decisions.
Keep changes uncommitted for review.

The reference repository already contains a backend, dashboard, database, event receiver, and tests. Its integration brief scopes the role; its backend build brief defines seven implementation milestones, including account erasure. The running fixture covers all six REST operations. Complete the real store, authentication, isolation, and deployment obligations of your selected profiles before using it as a production provider.

3. Try it as your customer#

Have AI start the app and give you the URL. Then follow this sequence using two test accounts, Alice and Bob:

  1. Buy as Alice. Complete a test purchase and open the paid feature. Try a pending or canceled purchase too; neither should unlock it.
  2. Switch to Bob. He must not see Alice’s paid content or take her purchase by submitting the same receipt.
  3. Recheck Alice’s access. For Apple/Google subscriptions, cancel renewal: paid content stays open until expiry. For Amazon/Horizon, return a negative store ownership answer: Premium disappears from the allowed products. Simulate a store outage too: it must report a failed read, then recover when the store is available. Reload at each point.
  4. Repeat and restart. Retry a purchase, then restart the backend. Ownership and access remain correct, with no duplicate fulfillment. If your provider emits lifecycle events, retry their delivery too. IAPKit currently emits those events for Apple/Google subscriptions.
  5. Delete Alice. Check that her identity is removed from the provider’s records and your own stored event copies. Bob’s records remain intact.

Ask AI to run the same checks automatically and show any failures. Keep those checks with the source, so the next change can be reviewed against the same behavior.

Start with test purchases. Before releasing, repeat the relevant flow with your store sandbox, real login, and deployed backend. Passing the contract checks and completing a real store purchase answer different questions; ask for both results.

Run the checks in both reference projects

Read the checks alongside the implementation

Run the flow locally

openiap-commerce-protocol-example

verify.mjs replays the purchase flow, expiry boundaries, signatures, retries, and receiver recovery. These checks explain what this small backend demonstrates; it makes no full-profile claim.

Read code: verifyLab
See the service implementation

IAPKit

The published conformance runner calls IAPKit’s real REST and GraphQL routes against fixture store/database I/O. Separate worker and mutation tests cover persistence responsibilities.

Read code: IAPKit dual-binding conformance
How to check this behavior

Example. Install dependencies, then run npm test in the example repository. Bun runs its HTTP server and SQLite. Inspect reference

IAPKit. Run bun run test -- server/api/commerce/conformance.test.ts convex/commerce/spec.conformance.test.ts from packages/kit. These are local contract checks, not live store tests. Inspect reference

Additional exercise: AI built a new fixture app

Field Notes is a subscription app built from the brief alone, in Node.js and SQLite, then reinstalled and rechecked in a clean copy.

Read the reproduction record for the prompt, runnable source, checks, and corrections. This exercise covers a local fixture app; real stores and production integration were not tested.

Keep the next change small#

For Apple/Google subscriptions, keep Premium available until the paid period ends. Both projects keep that decision in one function. Your database and event worker can change without rewriting what “has access” means.

Same access rule, different storage

Run the flow locally

openiap-commerce-protocol-example

isEntitled reads the subscription state and expiry. SQLite holds the records; entitlements returns only products Alice can use now. Turning renewal off does not end paid access.

Read code: isEntitled
See the service implementation

IAPKit

isEntitledAt applies the same rule to Convex records. entitlementsV2 reads the current time and returns allowed products without exposing store purchase tokens.

Read code: isEntitledAt
How to check this behavior

Example. The state checks test before, at, and after expiry with a controlled clock. Run npm test. Inspect reference

IAPKit. Account-read tests check token omission, server authorization, and time advancing past expiry. Inspect reference

For a new store, compare the verification adapters. For a new data service, compare the sender and receiver. Ask AI to change the part that owns the behavior and rerun its checks.

Account deletion: finish the responsibility

Delete the account in both implementations

Run the flow locally

openiap-commerce-protocol-example

Step 7 removes identity from purchases and event records atomically. The app erases delivered copies and remembers the deletion so late signed events cannot restore the user.

Read code: eraseUser
See the service implementation

IAPKit

eraseUser starts a project-scoped job. The worker removes identity from purchases, subscriptions, and events in batches, waiting for claimed deliveries before cleaning those events.

Read code: drainSubscriptionUserErasurePage
How to check this behavior

Example. Run bun verify-erasure.mjs. It checks active-account erasure, in-flight delivery, repeated jobs, late events, and restart. Inspect reference

IAPKit. Erasure request tests cover server authorization and repeated requests, including already completed jobs. Inspect reference

Run the reference when you need it#

AI can start the example dashboard for you. It runs locally without store credentials or environment variables, using Bun for HTTP and SQLite. The protocol itself does not require Bun.

Manual setup and runtime details
sh
git clone https://github.com/hyodotdev/openiap-commerce-protocol-example.git
cd openiap-commerce-protocol-example
npm ci
npm test
npm start

Open http://127.0.0.1:5181 and select Run step 1 →. HTTP, storage, and signatures are real local operations; store evidence and the clock are fixtures. Startup creates temporary databases; the recovery step reopens them inside the same process. The README has the full runtime and replay instructions.