Not Organic Developers

Not Organic / Integration guides

Billing & usage

Make spending explicit, understand the reservation lifecycle, and treat payments as a server-verified workflow.

Amounts and pricing

Rate version: 2026-09-09-retail-v2. A $1 wallet balance buys $1 of Not Organic services at retail rates, not $1 of upstream compute. Subscriptions and top-ups fund the same account; product restrictions and grant expiry still apply. Personal model training and voice are not included unless an offer explicitly says so.

The ledger uses integer microusd: 1 USD = 1,000,000 microusd. Avoid floating-point currency arithmetic. The pricing implementation adds a 100% markup to the configured upstream cost and rounds up to whole microusd.

Illustrative calculation
upstream cost:       1_000_000 microusd ($1.00)
with 100% markup:     2_000_000 microusd ($2.00)
difference:          1_000_000 microusd ($1.00)

The difference is 50% of the sale price before other costs. Markup is not gross margin. Product subscriptions and credit allowances follow the configured catalog, which may scope credit by product and expiry.

Reserve, dispatch, reconcile

  1. Reserve. The gateway checks authorization, idempotency, the route, and available funds before dispatching paid work.
  2. Dispatch. The provider may accept the work even if the client disconnects later.
  3. Reconcile. Usage settles the reservation; unused reserved value can be released. Missing usage requires conservative reconciliation. On the inference path, the gateway caps the user charge and records upstream costs above the cap as provider-absorbed cost.
The spending cap limits the gateway charge, not upstream computation.

x-notorganic-max-cost-microusd sets the request’s reservation and maximum gateway charge on the inference path. The provider may do more work than that amount covers; the gateway records the excess as absorbed cost. Use model output limits and monitored reconciliation to control the service’s upstream exposure.

The SDK defaults to a reservation when one is not supplied. Set an explicit amount appropriate to the user’s action instead of treating a library default as a product spending policy.

Idempotency and retries

Create one idempotency key per logical metered action and retain it across retries of that same action. Generate a new DPoP proof for every HTTP attempt. A reused proof is a replay, even when the operation’s idempotency key is unchanged.

Do not automatically resubmit a paid action after an ambiguous timeout with a new key. First determine whether it was accepted or completed. Aborting a stream does not guarantee a zero charge.

Create a checkout

Offer a subscription-free option: one-time $10, $25, or $50 USD credit packs. Purchased credit does not expire or renew automatically. An authenticated free account can buy and use credit without subscribing. Packs fund metered AI usage; they do not add paid storage, mailboxes, or other subscription features.

Use the configured IDs returned in GET /v1/wallet → checkout.packIds. Keating uses keating_pack_10/25/50, Stich stich_credit_10/25/50, Twyne twyne_credit_10/25/50, and Interleave interleave_pack_10/25/50. Each suffix is a separate pack ID. Availability depends on actual payment configuration. Never infer a successful payment from the checkout return page.

Use a token with billing:checkout. Supply a configured stable plan_id or pack_id, an HTTPS return_url, and an idempotency key. The gateway maps catalog IDs to allowlisted Paddle prices on the server.

TypeScript · checkout
const checkout = await client.billing.createPackCheckout(
  configuredPackId,
  "https://client.example/billing/return",
  { idempotencyKey: checkoutAttemptId },
);
// Navigate only after receiving a successful response with checkout.url.

Pack IDs are obtained from the approved product catalog, not invented in the client. A missing mapping can produce missing_billing_product; a configured price without a payment API key produces checkout_unavailable.

The response contains id, url, and provider: "paddle". The integration retains return_url as transaction metadata; it does not establish an automatic Paddle redirect to that URL.

Do not blindly retry checkout creation.

The current Paddle adapter includes the idempotency key in transaction metadata, but does not establish provider-side transaction deduplication. Retain a successful checkout URL and investigate an ambiguous attempt before creating another.

Verify payment before granting credit

A success page is not evidence of a paid transaction. The server must verify the signed provider notification, validate the product and event, and issue the entitlement or credit once. The repository’s Paddle webhook handling lives in convex/http.ts at /webhooks/paddle; configure the actual Convex HTTP endpoint as the notification destination.

Paddle checkout URLs need the configured payment-link domain and a correctly initialized Paddle.js checkout page. Returning a transaction URL alone does not prove that the browser payment flow works.

Before enabling real purchases, verify checkout, payment, signed webhook, entitlement, credit, metered debit, reconciliation, and refund in the appropriate test environment. This documentation does not claim that chain is currently proven in production.