Tools Shop is the provider-neutral funding layer for prepaid entitlements. Generic AI Credits use the shared AI billing ledger, while service-specific Job Search credits use a separate logical-run ledger. Neither balance is provider-specific.
Authenticated users can open /me/shop to see:
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.
Job Search credit products use type: job_search_credits and a positive integer job_search_credit_grant. Generic AI Credit products keep type: ai_credits with credit_grant_microusd. Google Play mappings in GOOGLE_PLAY_PRODUCTS_JSON may use either type. A verified Job Search-credit purchase is credited idempotently to the Job Search ledger; refunds/revocations create a compensating reversal just like generic AI-credit funding.
The following authenticated endpoints are available without API version prefixes. Normal account JWT authentication remains supported. The native Android client instead requests a dedicated owner-bound shop.manage credential during account sign-in with sync_shop_token=true; Android must not persist the account-session JWT or reuse its SocialGPT/Job Search credentials for Shop.
GET /api/shop/balanceGET /api/shop/purchasesGET /api/shop/transactionsGET /api/shop/productsPOST /api/shop/purchases/google-playbalance returns exact integer micro-USD fields: balance_microusd, reserved_microusd and spendable_microusd. Clients must not derive or submit authoritative balances themselves.
The dedicated Android Shop credential is accepted only for its owning user's Shop data and verified purchase claims. 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.
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.
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.
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; Job Search grants remain exact integer logical-run credits.
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.
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.