← Back to docs

Shop wallet and AI Credits

Shop and AI Credits

Tools Shop is the provider-neutral wallet layer for prepaid AI Credits. It uses the same AI credit ledger as the AI billing system and does not maintain a provider-specific balance.

My Shop

Authenticated users can open /me/shop to see:

  • current AI Credit balance;
  • reserved AI Credit amount;
  • spendable balance;
  • configured AI Credit products;
  • recent purchases;
  • recent immutable wallet transactions;
  • available top-up providers when an integration is enabled.

Ko-fi is treated as an enabled Shop provider when its webhook verification is configured. Active Ko-fi Shop AI top-up mappings created under /admin/support are automatically included in the Shop product catalog, so they do not need to be duplicated in config/shop.php. Inactive mappings are not shown as purchasable products.

Google Play is shown when its backend billing integration and at least one AI Credit product mapping are enabled. Google Play prices displayed by Android come from Google Play Billing; ToolsAPI remains authoritative for which Google product id maps to which fixed internal AI Credit grant.

If no payment provider is enabled, the wallet and history remain readable and no unusable checkout button is shown.

Owner API

The following authenticated endpoints are available without API version prefixes:

  • GET /api/shop/balance
  • GET /api/shop/purchases
  • GET /api/shop/transactions
  • GET /api/shop/products
  • POST /api/shop/purchases/google-play

balance returns exact integer micro-USD fields: balance_microusd, reserved_microusd and spendable_microusd. Clients must not derive or submit authoritative balances themselves.

products returns the active provider-neutral catalog. Google Play entries include provider: google_play and the provider product id as provider_product_code; Android should match that id against Google Play ProductDetails and use Google's localized display price.

To claim a completed Google Play purchase, Android sends only product_id, purchase_token and an optional correlation_id to POST /api/shop/purchases/google-play. Client-supplied prices, currencies or credit amounts are not accepted as authority. A pending purchase returns HTTP 202 without credit. A non-purchased/cancelled state returns HTTP 409 without credit. A completed purchase is verified server-side and credited idempotently.

Purchases and transactions are owner-scoped. A client cannot request another user's history through these endpoints, and a Google Play purchase already bound to another Tools user cannot be reassigned.

Google Play verification and RTDN

ToolsAPI verifies one-time products with the Google Play Android Publisher API before granting credit. The raw purchase token is never stored in Shop history; a deterministic SHA-256-derived purchase identity is used for idempotency and ownership checks. After entitlement persistence succeeds, ToolsAPI acknowledges an unacknowledged purchase server-side.

Google Play Real-time Developer Notifications are accepted at POST /api/shop/google-play/rtdn. The Pub/Sub push identity must match the configured OIDC audience and service-account email. RTDN is notification-only: ToolsAPI always queries Android Publisher for the authoritative current purchase state before crediting, reversing or otherwise mutating Shop state.

A purchased RTDN received before Android claims the purchase is stored as unmatched provider state without granting credit. The authenticated Android claim can later bind and reconcile it exactly once. An authoritative cancellation/refund/revocation for a previously credited purchase creates a compensating funding_reversal transaction rather than deleting history.

Payment verification flow

Provider integrations use the common Shop purchase-ingestion layer only after provider verification. Each provider adapter is responsible for validating its own provider event and translating it into the same normalized payment contract. Providers can therefore be added, enabled or disabled independently without changing the wallet contract or depending on another provider integration.

Unknown or disabled providers are rejected before Shop accounting is called. Provider callbacks do not write balances directly. Verified purchases, unmatched payments, rejected payments and provider reversals are all routed through the canonical Shop accounting services.

Accounting contract

Provider adapters must verify their payment with the provider before asking the Shop ingestion service to grant credit. The normalized purchase identity consists of provider plus immutable provider purchase id, with provider event id used as an additional idempotency key when available.

A verified matched purchase may create one funding_credit transaction. Replays do not grant credit again. Refunds and reversals create compensating funding_reversal transactions instead of editing or deleting earlier ledger history.

Unmatched or rejected purchases can be stored for reconciliation without changing a balance. Internal AI Credit grants remain exact integer micro-USD amounts.

Payment verification or accounting failures that could otherwise lose money or double-credit are reported through Tools operational diagnostics independently of the structured payment audit trail. Diagnostic and audit records carry safe provider, action, result, resource and correlation context without provider credentials or raw purchase tokens.

Administration

Administrators can open /admin/shop to review provider-neutral purchases, user mapping, purchase state, correlation id and immutable AI Credit transactions. Manual balance adjustments reuse the existing AI credit accounting service and are separately recorded in the ledger.

Ko-fi Shop top-up mappings remain managed under /admin/support. Google Play product mappings and provider credentials are deployment configuration and are never exposed through Shop API responses.