# Creator-funded AI credits Hackemist's shared AI gateway uses a separate prepaid **app wallet** for each app. Its creator funds the wallet; requests made by that app's users spend the creator's credits. Balances start at zero. A provider's own billing account remains the administrator's responsibility. ## Configure costs and purchases In **Admin → AI providers**: 1. Add the provider, API key and enabled role/model assignments described in the [AI integration guide](/docs/ai-providers.md). 2. Set each provider's **Default credits per request**. Set a role's optional override when, for example, image or video generation should cost more than general text. Costs are positive whole credits from 1 to 1,000,000. There is no app-controlled price or free-rate setting. 3. Configure **Creator AI credit purchases**: Stripe or Paystack, a supported currency, and priced credit packs. Each pack has an ID, name, whole credits and a price. Browser forms use normal currency amounts; the API stores integer minor units, including zero-decimal currencies. 4. Configure the selected payment provider's credentials and approval/legal settings in **Site settings**, then enable credit purchases. One-time credit checkout does not require enabling membership subscriptions or creating a subscription plan. Live Paystack USD payments require an eligible NG/KE account with confirmed international acceptance and USD settlement. 5. Save the AI configuration. Saving does not create checkout or call a paid AI generation API. Costs are **per dispatched generation request**, not a provider's measured token bill. Text output limits and the typed image/video/audio contracts bound each request. Set rates to cover your expected provider costs. A role override changes future reservations; existing reservations keep their original rate and configuration revision. Configure provider-account spending limits separately. ## Creator workflow In an app's **Studio → App details → AI features**, select its AI roles and open **Manage app AI credits**. The dialog shows its available balance, current costs, pending reservations, purchase history and credit ledger. Choose a pack, review the exact price and confirm before leaving for hosted checkout. The creator's account email is sent to the payment provider. Hackemist does not handle card details. Returning to Studio checks the original payment with the provider. The return URL alone never credits a wallet. **Check payment** can check a purchase again without creating another checkout or payment. Signed provider webhooks also reconcile saved orders: - Stripe: `POST /api/billing/webhook`. - Paystack: `POST /api/billing/paystack/webhook`. The server verifies the canonical order, creator, app, payment account/mode, receipt, amount and currency. Each original payment funds its wallet at most once even when the browser return and duplicate notifications arrive together. Saved orders retain their original pack units and price when the catalog later changes. A stable checkout request key prevents a retry from creating another order. An uncertain checkout remains available for reconciliation; it is not automatically recreated. **Test-mode payments never add spendable AI credits.** They can exercise checkout and receipt verification. Administrators can explicitly add an audited test allowance if needed, but shared provider calls can still incur actual provider costs. ## Exhaustion, reservations and failures Before any generation, the server atomically reserves that app's rate and checks current authorization, service configuration and daily/concurrent limits. Concurrent workers cannot spend the same credits. No SQL writer remains open during a provider request. An app that cannot cover the next request receives HTTP **402**, reason `AI_CREDITS_REQUIRED`, before its content reaches the provider. The player reports that the creator must fund the app. Other funded apps continue operating. A new verified purchase allows the next request to proceed without republishing the app. Existing accepted async jobs can still be polled without buying credits or charging again. A successfully accepted generation consumes the reservation once, including an accepted async job. An explicit provider refusal such as invalid credentials or rate limiting releases it. A timeout, broken connection, invalid result, lost response or failed media retrieval can follow billable work, so it retains the reserved debit as **uncertain**. The gateway never retries generation or releases these units automatically. Daily attempt limits still count failed dispatches. In **Manage creator funding**, an administrator can reconcile an uncertain reservation, or a reservation still pending after ten minutes, as charged or uncharged after checking the provider. Releasing returns its reserved units once; consuming records the charge without a second debit. A required reason and administrator identity are audited. Verified refunds revoke proportional pack credits, rounded up. Disputes and uncertain Paystack refunds revoke all units from the affected pack pending operator review. Reconciliation is monotonic: an older notification cannot restore revoked credits. If the creator already spent the refunded units, the wallet can become negative and new AI requests stop. Resolve a won dispute or another financial correction through an explicit audited admin adjustment after checking the provider. These APIs verify existing payments; they do not initiate refunds or resolve provider disputes. ## Administrator exemptions and adjustments - **An app:** Admin → AI providers → **Manage creator funding** → its **Funding bypass**. - **A creator:** Admin → **Accounts & access** → that account's **AI funding bypass**. This applies across that creator's apps. - **An allowance/correction:** **Manage creator funding → Adjust credits**, with a signed whole-credit change and reason. Either enabled exemption allows the app to use configured AI roles without prepaid credits. Daily limits, launch/session checks and sharing consent still apply. Disabling both exemptions restores the normal funding check immediately. Exemptions never make a request consume another app's credits. Administrative changes require a current admin session, CSRF and a recorded reason; exemption edits also require a current revision. There is no automatic exemption for an administrator's own apps. **Reconcile payment** in the same panel checks a saved credit order against the provider. For a lost Stripe initialization response, the administrator can provide the original `cs_…` checkout session ID from the provider console; canonical metadata, amount, creator and mode must still match. It cannot create a new payment. Changing an app's owner intentionally stops wallet spending/funding until an administrator reconciles the old owner's funds. ## Developer and MCP contract Apps use the same [launch-bound SDK](/docs/ai-providers.md). They do not purchase credits or hold payment/provider secrets. Check funded status and handle a rejected request while preserving the user's work: ```js const info = await Hackemist.ai.capabilities(); if (!info.roles.general?.funded) { showStatus('AI is paused. Ask the app creator to fund AI credits.'); } else { try { const result = await Hackemist.ai.generate({ role: 'general', input: {prompt: documentText} }); if (result.status === 'completed') showSummary(result.text); } catch (error) { showStatus(error.message); } } ``` The player exposes only a per-role `funded` boolean, not the creator's wallet balance or purchase details. A balance can change between capability discovery and generation, so the server always checks again. `ai_credits_get({project_id})` with `projects:read` returns an owned, credential-scoped app's balance, reserved units, bypass and current rates. It is read-only. MCP cannot create payments, credit a wallet, set exemptions or perform paid runtime generation. This document is also `hackemist://docs/ai-credits`. Browser APIs use current account cookies and CSRF for mutations: | Endpoint | Purpose | | --- | --- | | `GET /api/projects/{id}/ai/credits` | Creator wallet, rates, packs, recent ledger and orders | | `POST /api/projects/{id}/ai/credits/checkout` | Confirmed `{pack_id, request_key, config_revision, consent:true}` | | `POST /api/projects/{id}/ai/credits/orders/{order}/verify` | Verify an owned original order, empty object body | | `GET /api/admin/ai/credits` | Admin wallets, exemptions, pending review and recent orders | | `POST /api/admin/ai/credits/adjust` | `{project_id, delta, reason, request_key}`; idempotent stable key | | `GET/PUT /api/admin/ai/credits/bypass` | Read `{scope,target_id}`; write also `{enabled,reason,base_revision}` | | `POST /api/admin/ai/credits/holds/{request}` | `{decision:'release'|'consume',reason}` after reconciliation | | `POST /api/admin/ai/credits/orders/{order}/verify` | `{reason,provider_id:null}`; original Stripe session ID only when unknown | Request keys are stable, unique strings of 16–64 ASCII letters, digits, underscores or hyphens; UUIDs work. Scope is `project` or `creator`. Rates and funding settings are part of the encrypted, revisioned admin AI registry, configured through `PUT /api/admin/ai`; they are not generic settings keys. PostgreSQL migration **15** adds five tables for wallets, ledger, holds, exemptions and orders. SQLite initialization and portable backup/transfer metadata include them. Financial records persist beyond the seven-day AI request metadata window. Use the platform's normal encrypted backups and retain `SETTINGS_KEY`. Upgrade the control/runtime images and frontend together; credit purchases remain disabled until configured, and existing installations receive no automatic funds or exemptions. ## Payment API references - [Stripe one-time Checkout creation](https://docs.stripe.com/api/checkout/sessions/create), [canonical session retrieval](https://docs.stripe.com/api/checkout/sessions/retrieve), and [captured charge/refund fields](https://docs.stripe.com/api/charges/object). - [Paystack transaction initialization/verification](https://paystack.com/docs/api/transaction/), [refund collection](https://paystack.com/docs/api/refund/), and [transaction-filtered disputes](https://paystack.com/docs/api/dispute/).