> ## Documentation Index
> Fetch the complete documentation index at: /docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Stripe Payments

> Understand Crave's per-location Stripe setup and direct-charge storefront flow.

Crave's online-payment design uses one Stripe connected account per Crave
location. Direct charges and Stripe processing costs belong to that location's
Stripe account. Stripe automatically pays out available funds to its confirmed bank account.
Crave orchestrates checkout and receives a separate application fee.

> [!NOTE]
>
> Online payments require a verified Stripe account and confirmed bank for each
> location. Stripe schedules payouts automatically; merchants do not need Crave
> to release each payout. Ordinary orders and catering payments use the same
> location readiness checks. Stripe determines country, currency, capability,
> settlement timing, and bank availability for each account.

## Separate managed Cloud hosting product

The separately deployed managed Cloud hosting product uses a merchant-owned Stripe account.
It charges a hosting subscription and takes no order
application fee. Its included storefront uses its own pinned runtime; those
commercial terms and compatibility observations do not activate the direct-charge
platform source candidate described here. See the
[Cloud release results](/docs/guides/crave-cloud-overview.md#developer-package-compatibility)
before choosing a client or enabling payments for a Cloud installation.

## Environment model

Sandbox and production are separate deployments with separate databases, Clerk
applications, Stripe credentials, connected accounts, and API-key namespaces.
There is no merchant test/live toggle inside one Crave organization.

| Environment | Business Manager | Storefront API | API key prefix | Stripe key family |
| - | - | - | - | - |
| Sandbox | `https://sandbox.dashboard.craveup.com` | `https://sandbox-api.craveup.com/api/v1/storefront` | `crv_test_...` | `pk_test_...` |
| Production | `https://dashboard.craveup.com` | `https://api.craveup.com/api/v1/storefront` | `crv_live_...` | `pk_live_...` |

Create and verify the organization and every location independently in the
environment you intend to use. Never send a sandbox credential to production or
a production credential to sandbox. Each deployment also uses its own Clerk
application, so signing in to one environment does not create a session or
organization in the other.

## Location payment-account flow

Creating an organization or location does not automatically create a Stripe
account. An organization administrator starts setup explicitly for each location:

**1. Choose the location**

In Business Manager, switch to the intended location and open **Settings >
Account**. Confirm that the location name and address are correct before
starting payment setup.

**2. Confirm the payment-account contact**

Enter and confirm the email that owns this location's Stripe payment setup.
Crave stores this contact with the location payment account; it does not
reuse an order-notification email silently.

**3. Complete Stripe-hosted onboarding**

Continue to Stripe's one-time hosted onboarding flow. Supply the legal,
identity, tax, and bank information Stripe requests. A second location may
be offered eligible information reuse, but every location must satisfy the
requirements Stripe returns for its own account.

**4. Resolve requirements in Business Manager**

Return to **Settings > Account** for status, notifications, documents, and
required account-management actions. Crave does not depend on a separate
provider-hosted merchant dashboard for this flow.

**5. Confirm the payout destination**

An organization administrator confirms the exact current external account. A
bank-account change invalidates the prior confirmation and blocks payment
and payout readiness until the new destination is confirmed.

Stripe readiness is per location. An incomplete second location must not block a
different location that has completed its own requirements. A pay-at-store-only
location can remain without a Stripe payment account.

## Storefront payment flow

The storefront uses a capability-protected Crave cart. Crave selects the
location account and creates the PaymentIntent as a direct charge in that
account; the browser cannot choose or replace the account.

1. Submit the canonical order with the authorized cart revision and accepted evidence.
2. Read the server-selected `connectedAccountId` and `clientSecret` from a
   `CUSTOMER_ACTION_REQUIRED` outcome.
3. Initialize Stripe.js with the publishable key for the current deployment and
   the exact connected account returned by Crave.
4. Confirm through Stripe Elements. Crave finalizes payment and the order only
   from authoritative Stripe event or reconciliation evidence.

```tsx filename="app/checkout/page.tsx" theme={null}
import { loadStripe } from "@stripe/stripe-js";
import { Elements } from "@stripe/react-stripe-js";

const outcome = await storefront.checkout.submitOrder(
  locationId,
  cartId,
  {
    acceptedCatalogEvidence,
    acceptedDiscountEvidence,
    collectionMode: "ONLINE",
    customerConfirmationRevision,
    quoteFingerprint,
  },
  { idempotencyKey, revision: cart.revision },
);

if (outcome.status !== "CUSTOMER_ACTION_REQUIRED") return;

// connectedAccountId is server-selected and must remain unchanged for
// confirmation, redirect recovery, and payment-status lookup.
const stripe = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!, {
  stripeAccount: outcome.connectedAccountId,
});

<Elements stripe={stripe} options={{ clientSecret: outcome.clientSecret }}>
  <PaymentForm />
</Elements>;
```

Only the Stripe publishable key belongs in browser configuration. Stripe secret
keys, connected-account credentials, private Crave API keys, saved payment
credentials, and webhook secrets remain server-side.

For the complete checkout contract, continue to the
[Accept Payments guide](/docs/guides/accept-payments.md).

## Sandbox verification

Until the activation lock is removed, a payment-session request must return the
documented activation failure rather than creating a charge. That failure is the
correct sandbox result; do not bypass it or substitute a platform-only payment.

After activation, verify the exact release with the sandbox Business Manager,
sandbox Storefront API, and `pk_test_...` publishable key. Cover:

* successful card payment;
* authentication-required payment and browser recovery;
* declined payment;
* full and partial refund evidence;
* application-fee refund evidence;
* dispute evidence and response access;
* payout-destination change and readiness invalidation; and
* a second location with independent onboarding and payment-account ownership.

Use Stripe test cards only in the sandbox deployment. Never use test card data
in production.

## Troubleshooting

### "Online payments are not activated"

The release-wide direct-charge gate is still closed. Continue testing catalog,
cart, pay-at-store, and other non-Stripe behavior; do not retry through another
Stripe account or weaken the gate.

### "Payment account needs attention"

* Select the exact affected location in Business Manager.
* Open **Settings > Account** and continue the Stripe-hosted or embedded action
  shown there.
* Confirm that all required capabilities and documents are complete.
* Reconfirm the current payout destination after any external-account change.

### Account or environment mismatch

* Confirm the storefront is calling the intended sandbox or production API.
* Confirm the publishable key belongs to that same environment.
* Discard the payment session and start again when the returned connected
  account does not match the current location; never override it in the browser.

<Snippet file="need-help.mdx" />


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.