Stripe Issuing for AI purchasing
Atta issues cards through Stripe Issuing. Each workspace connects its own Stripe account, so cards spend that workspace's balance and Atta never holds funds. After an order is approved, Atta creates one single-use card capped at the approved total, authorizes each charge in real time, and settles the budget from the card's events.
How the program is set up
A card spends the balance of the Stripe account it was issued on. Atta doesn't issue from a shared balance. Each workspace has a card program on its own connected account, created through Stripe Connect with Issuing enabled.
The program holds the cardholder (the company name and billing address cards are issued under) and the allowed merchant categories. A program has to allow at least one category, because a card with none declines everything.
How a card is issued and capped is on the virtual cards page; below is the Stripe account side.
What Atta creates
- One card per order, issued after approval and reservation, with a limit equal to the approved total set as both a per-authorization and an all-time limit.
- An idempotency key per attempt (
card:<orderId>:<attemptId>). Stripe replays the answer for a key it has seen, and that answer could be a card Atta already cancelled. - A card that expires with the 24 hour abandon window. The sweep cancels unused ones.
- An inactive card during an undo window, activated when the window closes.
What Atta listens for
Atta's endpoint at /api/webhooks/issuing handles:
| Event | What happens |
|---|---|
issuing_authorization.request | Answered inside Stripe's 2 second window with the pure authorization check: card active, order in checkout, same currency, amount at or under the limit, category allowed, merchant matches the pinned one |
issuing_authorization.created | Order becomes paid, reservation kept, merchant pinned on the first approval |
issuing_transaction.created | Settles the captured amount, releases any difference under the reservation |
| Refund transactions | Release the refunded amount once, keyed by Stripe's transaction id |
account.updated | Re-reads the account's status |
account.application.deauthorized | Stops issuing and leaves existing holds alone |
If Atta is down, Stripe falls back to the card's own limits, so the cap still holds.
An event whose account differs from the card row's account moves nothing and the authorization is declined. A valid signature proves Stripe sent the event, not that it belongs to that workspace's card.
Setting it up
The first two steps are the operator's. The rest are in the workspace.
- Operator: enable Issuing on the platform's Stripe account and set
CARD_ISSUER=stripe,STRIPE_ISSUING_SECRET_KEYandNEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY. In production the operator also lists the workspaces allowed to issue inCARD_WORKSPACES. - Operator: add the webhooks. Point Issuing's real-time authorization webhook and a Connect endpoint at
https://<your-host>/api/webhooks/issuing, with the secrets inSTRIPE_ISSUING_WEBHOOK_SECRETandSTRIPE_ISSUING_CONNECT_WEBHOOK_SECRET. - Workspace owner: in Settings, then Virtual cards, enter the country and press Connect a Stripe account. Only the owner can. Finish Stripe's hosted onboarding.
- Back in Settings, Atta reads the account's status. When it's active, someone with budget management turns cards on and enters the company name and billing address.
The account id always comes from Stripe and never from a form, and a unique index stops two workspaces sharing one. Until the account is active, the program doesn't issue, and it never falls back to the app's balance.
A card spends the connected account's Issuing balance, so that balance has to be funded in Stripe.
Revealing the card
The number and CVC are shown to the requester in Stripe's own frame on the order page. They don't enter Atta's database, logs or messages.
In development, use Stripe test mode. It's the real API with test cards.
Questions
Whose money does the card spend?
The workspace's. Each workspace connects its own Stripe account and cards are issued on that account's balance. Atta doesn't hold or move funds.
Who can connect the Stripe account?
The workspace owner. An admin can't, because it needs workspace management. Turning cards on afterwards needs budget management.
What if the Stripe account is restricted?
The program stops issuing and doesn't fall back to another balance. Cards already issued keep their holds, and owners get a notification when the account is restricted or deauthorized.
Does a card program change approvals?
No. The approval policy decides first. The card enforces the approved figure at the store afterward.
Related
- Virtual cards for purchases an AI agent makesAtta issues one single-use Stripe Issuing card per approved order, capped at the approved total and checked on every charge. The number never enters the app.
- Spend management softwareA budget reserves money at checkout and settles it on payment. Released if the order is cancelled or abandoned. One currency per budget, no double counting.
- Purchase approval softwareSet approval limits per role and build approval chains by amount. Approvers answer from Slack, WhatsApp or the app, and nothing is paid until the last step clears.
- Buy from your Shopify store with an AI agentConnect a Shopify store to Atta. The agent searches its catalog, builds the cart, hands off Shopify checkout, and settles the budget from the store's webhooks.