# Source: https://docs.stripe.com/financial-accounts/connect/examples/sample-app.md

# Source: https://docs.stripe.com/issuing/sample-app.md

# Issuing and Financial Accounts for platforms sample app

Learn how to onboard customers, issue cards, and make outbound payments.

You can find the app’s [complete source code](https://github.com/stripe-samples/issuing-treasury) on GitHub.

To see how you can use Issuing and Financial Accounts for platforms APIs in your integration, try our sample app. It lets you onboard as a customer, create cards, test authorizations, and make outbound payments from a financial account.

Without writing any code, you can also copy the sample app to use with your platform, following the API logs generated by your actions.

[Try our sample app](https://baas.stripe.dev/auth/register)
[![The Issuing and Financial Accounts for platforms demo app Card details page](https://b.stripecdn.com/docs-statics-srv/assets/issuing-treasury-demo-app.54ad51387e0606a4b240347f4cb02cfb.png)

The Issuing and Financial Accounts for platforms sample app card details page
](https://baas.stripe.dev/auth/register)
This app is for [platforms onboarding business customers](https://docs.stripe.com/issuing/connect.md#when-to-use-connect). If you only need cards for yourself or your own employees, use [Issuing in the Dashboard](https://dashboard.stripe.com/test/issuing/overview) instead.

# Try our sample app

> This is a Try our sample app for when use-or-copy-sample-app is use-sample-app. View the full page at https://docs.stripe.com/issuing/sample-app?use-or-copy-sample-app=use-sample-app.


# Copy the sample app

> This is a Copy the sample app for when use-or-copy-sample-app is copy-sample-app. View the full page at https://docs.stripe.com/issuing/sample-app?use-or-copy-sample-app=copy-sample-app.


# Try our sample app

> This is a Try our sample app for when use-or-copy-sample-app is use-sample-app. View the full page at https://docs.stripe.com/issuing/sample-app?use-or-copy-sample-app=use-sample-app.

## Create an account with the platform

To use the sample app, first [create an account](https://baas.stripe.dev/auth/register) to onboard as a customer of the platform.

After you provide an email and password, the app’s backend creates a connected account and requests the `card_issuing` and `treasury` capabilities.

> #### Accounts v2 API compatibility
> 
> The Accounts v2 API doesn’t support Issuing and Financial Accounts workflows. If you have accounts created with Accounts v2, you can use Accounts v1 to manage the `treasury` and `card_issuing` capabilities. For details, see [Use Accounts as customers](https://docs.stripe.com/connect/use-accounts-as-customers.md).

### (Optional) Simulate hosted onboarding to provide full account details

To simulate hosted onboarding, complete the following steps using [test tokens](https://docs.stripe.com/connect/testing.md#identity-verification) to prevent errors. We’ve pre-filled the account data for this app.

1. Uncheck **Skip the rest of onboarding**.

1. Click **Confirm** on the **Test data** dialog.

1. Click **Continue** to be redirected to Stripe’s [hosted onboarding](https://docs.stripe.com/connect/custom/hosted-onboarding.md) flow.

1. On the **Let’s get started** screen, enter:

   - **Mobile number**: 000-000-0000
   - **Email**: Any fake email address

1. At **Verify your mobile number**, click **Use test code**.

1. At **Verify your identity**, click **Skip this step**.

After you submit the form, you’re redirected back to the app dashboard.

### See the code and API logs for these steps

After you complete the steps to onboard your first account in your copy of the sample app, review the corresponding API logs. The following code snippets happen in the backend when onboarding an account.

1. Create a [connected account](https://docs.stripe.com/financial-accounts/connect/account-management/connected-accounts.md) with the following capabilities: `transfers`, `card_issuing`, and `treasury`. Issuing only supports connected accounts that don’t use a Stripe-hosted Dashboard, and where your platform is responsible for requirements collection and loss liability, also known as a Custom connected account. Learn how to [create connected accounts](https://docs.stripe.com/connect/interactive-platform-guide.md?connect-charge-type=direct&connect-loss-liability-owner=platform) that work with Issuing. Copy our app to view the API logs, and find: [POST to /v1/accounts](https://dashboard.stripe.com/test/logs?method%5B0%5D=post&path=%2Fv1%2Faccounts).

   ```javascript
   const account = await stripe.accounts.create({
     controller: {
       stripe_dashboard: {
         type: "none"
       },
       fees: {
         payer: "application"
       },
       losses: {
         payments: "application"
       },
       requirement_collection: "application",
     },
     country: "US",
     email: email,
     capabilities: {
       transfers: { requested: true },
       treasury: { requested: true },
       card_issuing: { requested: true },
     },
   });
   ```

1. Create a [financial account](https://docs.stripe.com/financial-accounts/connect/account-management/financial-accounts.md). Copy our app to view the API logs, and find: [POST to /v1/treasury/financial_accounts](https://dashboard.stripe.com/test/logs?method%5B0%5D=post&path=%2Fv1%2Ftreasury%2Ffinancial_accounts).

   ```javascript
   const financialAccount = await stripe.treasury.financialAccounts.create(
     {
       supported_currencies: ["usd"],
       features: {
         card_issuing: { requested: true },
         deposit_insurance: { requested: true },
         financial_addresses: { aba: { requested: true } },
         inbound_transfers: { ach: { requested: true } },
         intra_stripe_flows: { requested: true },
         outbound_payments: {
           ach: { requested: true },
           us_domestic_wire: { requested: true },
         },
         outbound_transfers: {
           ach: { requested: true },
           us_domestic_wire: { requested: true },
         },
       },
     },
     { stripeAccount: account.id }
   );
   ```

1. Create a [Connect Onboarding link](https://docs.stripe.com/connect/custom/hosted-onboarding.md#info-to-collect) and use it to redirect new users to collect the necessary profile information for the requested capabilities. Copy our app to view the API logs, and find: [POST to /v1/account_links](https://dashboard.stripe.com/test/logs?method%5B0%5D=post&path=%2Fv1%2Faccount_links). The response to the Account Links request includes a value for the `url` used to redirect the user into the onboarding flow.

   ```javascript
   const { url } = await stripe.accountLinks.create({
     type: "account_onboarding",
     account: "{{CONNECTED_ACCOUNT_ID}}",
     refresh_url: connectOnboardingRedirectUrl + "/onboard",
     return_url: connectOnboardingRedirectUrl + "/onboard",
   });
   ```

1. After you complete onboarding, the account’s capabilities [status](https://docs.stripe.com/api/capabilities/object.md#capability_object-status) changes from `inactive` to `active`. View the `account.updated` event on the connected account at *https://dashboard.stripe.com/{{CONNECTED\_ACCOUNT\_ID}}/test/events?type=account.updated*. You can find the connected account’s ID in the response to step 1.

## Add funds to the financial account

1. On the **Overview** page, click **Generate test data**, and then click **Simulate received credit** in the drawer.

1. The transaction appears as a [received credit](https://docs.stripe.com/financial-accounts/connect/moving-money/into/received-credits.md) (an incoming ACH) for 500 USD, and appears in the [transaction receipt](https://docs.stripe.com/financial-accounts/connect/moving-money/regulatory-receipts.md).

1. Go to the **Financial account** page to [view your account number](https://docs.stripe.com/financial-accounts/connect/account-management/financial-accounts.md#retrieve-a-financialaccount-and-account-number).

### See the code and API logs for these steps

Use the following code samples and API logs to learn more about these steps.

### ReceivedCredit test helper

In testing environments, you can add funds to a financial account using the [ReceivedCredit test helpers](https://docs.stripe.com/api/treasury/received_credits/test_mode_create.md). This test helper simulates receiving a transfer from an external bank account into your financial account. Copy our app to view the API logs, and find: [POST to /v1/test_helpers/treasury/received_credits](https://dashboard.stripe.com/test/logs?showIP=false&method%5B0%5D=post&path=%2Fv1%2Ftest_helpers%2Ftreasury%2Freceived_credits).

```javascript
const receivedCredit = await stripe.testHelpers.treasury.receivedCredits.create(
  {
    amount: 50000,
    currency: "usd",
    financial_account: "{{FINANCIAL_ACCOUNT_ID}}",
    network: "ach",
  },
  { stripeAccount: "{{CONNECTED_ACCOUNT_ID}}" }
);
```

## Make an outbound ACH payment

You can enter any routing and account number, but the app processes the test payment using Stripe’s [test numbers for outbound payments](https://docs.stripe.com/financial-accounts/connect/moving-money/out-of/outbound-payments.md#testingobp)

1. On the **Financial account** page, click **Send money**.
1. Select **ACH**, then enter the recipient’s information and the amount to send.
1. Select `POSTED` as the transaction result to simulate a completed payment.
1. The transaction appears as an [outbound payment](https://docs.stripe.com/financial-accounts/connect/moving-money/out-of/outbound-payments.md).

### See the code and API logs for these steps

Use the following code samples and API logs to learn more about these steps.

### Send money interface

The money sending feature in the sample app uses the Financial Accounts for platforms `OutboundPayment` feature. You can use [OutboundPayments](https://docs.stripe.com/financial-accounts/connect/moving-money/out-of/outbound-payments.md) to send money to a third party’s external account. Copy our app to view the API logs, and find: [POST to /v1/treasury/outbound_payments](https://dashboard.stripe.com/test/logs?method%5B0%5D=post&path=%2Fv1%2Ftreasury%2Foutbound_payments). The response should show the payments status is `processing`.

```javascript
const outboundPayment = await stripe.treasury.outboundPayments.create(
  {
    financial_account: "{{FINANCIAL_ACCOUNT_ID}}",
    amount: 100,
    currency: "usd",
    statement_descriptor: req.descriptor,
    destination_payment_method_data: {
      type: "us_bank_account",
      us_bank_account: {
        account_holder_type: "company",
        routing_number: "110000000",
        account_number: "000000000009",
      },
    },
  },
  {
    stripeAccount: "{{CONNECTED_ACCOUNT_ID}}",
  }
);
```

### Set the transaction result with a test helper

After you select the transaction result in the web app, the outbound payments status is updated through a [test helper endpoint](https://docs.stripe.com/financial-accounts/connect/moving-money/out-of/outbound-payments.md#outboundpayment-test-helper-endpoints). Copy our app to view the API logs, and find: [POST to /v1/test_helpers/treasury/outbound_payments/{{OUTBOUND_PAYMENT_ID}}/post](https://dashboard.stripe.com/test/logs?method%5B0%5D=post&path=%2Fv1%2Ftest_helpers). The response should show the payments status is `posted`.

```javascript
const outboundPayment = await stripe.testHelpers.treasury.outboundPayments.post(
  {{OUTBOUND_PAYMENT_ID}},
);
```

## Create a cardholder, card, and make a test purchase

1. On the **Cardholder** page, click **Create a new cardholder**.
1. Enter the cardholder’s information, then click **Issue card** to create a virtual card.
1. You’re redirected to the **Cards** page. Click **Details** on the card row to view the new virtual card.
1. Click **Generate test data**, then **Simulate test purchase.**

### See the code and API logs for these steps

Use the following code samples and API logs to learn more about these steps.

### Create a cardholder

Create a `Cardholder` through the Stripe Issuing [create cardholder](https://docs.stripe.com/api/issuing/cardholders/create.md) API:

```javascript
const cardholder = await stripe.issuing.cardholders.create(
  {
    type: "individual",
    name: firstName + " " + lastName,
    email: email,
    individual: {
      first_name: firstName,
      last_name: lastName,
      card_issuing: {
        user_terms_acceptance: {
          date: Date.now(),
          ip: ip,
        },
      },
    },
    billing: {
      address: {
        city: city,
        line1: address1,
        state: state,
        postal_code: postalCode,
        country: country,
      },
    },
  },
  {
    stripeAccount: "{{CONNECTED_ACCOUNT_ID}}",
  }
);
```

### Create a card

After you create a `Cardholder`, you can issue a card to the `Cardholder` using the [create card](https://docs.stripe.com/api/issuing/cards/create.md) API. Set the card’s `financial_account` to the `ID` of the financial account you created in step 2.

```javascript
const card = await stripe.issuing.cards.create(
  {
    cardholder: cardholderId,
    financial_account: {{FINANCIAL_ACCOUNT_ID}},
    currency: 'usd',
    type: 'virtual',
    status: 'active',
  },
  {
    stripeAccount: "{{CONNECTED_ACCOUNT_ID}}"
  },
);
```

### Create a test purchase

After you create the authorization from the Dashboard, find the API log: [POST to /v1/test_helpers/issuing/authorizations](https://dashboard.stripe.com/test/logs?method%5B0%5D=post&path=%2Fv1%2Ftest_helpers%2Fissuing%2Fauthorizations). And after you capture the authorization from the Dashboard, find the API log: [POST to /v1/test_helpers/issuing/authorizations/{{AUTHORIZATION_ID}}](https://dashboard.stripe.com/test/logs?method%5B0%5D=post&path=%2Fv1%2Ftest_helpers%2Fissuing%2Fauthorizations%2F*).

## Optional: Temporarily pause spending on a card

1. On the **Cards** page, click **Details** for a card.
1. Click **Deactivate Card**. Below this button, the [status](https://docs.stripe.com/api/issuing/cards/object.md#issuing_card_object-status) changes to `inactive`.
1. Click **Generate test data** and follow the link to view the card from the Dashboard.
1. In the Dashboard, click **Create a test purchase**. On the next page, the authorization is declined.
1. Return to the web app to view details of the declined authorization.
1. Click **Activate Card** to change the card’s status from `inactive` back to `active`.

> #### Copy the sample app to complete steps 3-6
> 
> When you [copy the sample app](https://docs.stripe.com/issuing/sample-app.md?use-or-copy-sample-app=use-sample-app) and use it with your own Stripe API keys, use the Dashboard to create a test purchase.

### See the code and API logs for these steps

Use the following code samples and API logs to learn more about these steps.

### Switch a card’s status to inactive

After you click **Deactivate**, the card `status` is switched to `inactive`. Copy our app to view the API logs, and find: [POST to /v1/issuing/cards/{{CARD_ID}}](https://dashboard.stripe.com/test/logs?method%5B0%5D=post&path=%2Fv1%2Fissuing%2Fcards%2F*).

```javascript
const card = await stripe.issuing.cards.update(
  {{CARD_ID}},
  {
    status: 'inactive',
  }
);
```

### Test authorization declined because the card wasn’t active

After you create the authorization from the Dashboard, find the API log: [POST to /v1/issuing/cards/{{CARD_ID}}/test/authorizations](https://dashboard.stripe.com/test/logs?method%5B0%5D=post&path=%2Fv1%2Fissuing%2Fcards%2F*%2Ftest%2Fauthorizations). The authorization’s [approval](https://docs.stripe.com/api/issuing/authorizations/object.md#issuing_authorization_object-approved) is `false`.

Then, view the `issuing_authorization.created` event on the connect account at *https://dashboard.stripe.com/{{CONNECTED\_ACCOUNT\_ID}}/test/events?type=issuing\_authorization.created*. The authorization [request_history](https://docs.stripe.com/api/issuing/authorizations/object.md#issuing_authorization_object-request_history) shows `'approved: false, 'reason': 'card_inactive'`

## Optional: Pay out from the account's payments balance into the financial account

1. On the **Test data** page, click **Create PaymentLink**, and then **Go to PaymentLink**.

1. Enter any email, name, and postal code, using `4000 0000 0000 0077` as the card number.

   - With this test card, funds are added to the account’s available balance immediately.

1. Complete the payment, then return to the web app **Test Data** page and refresh the page.

1. Under **Create Payout**, the connected account’s available balance shows 9.41 USD.

1. Click **Add Financial Account as External Account** to set the connected account’s default external account for payouts to the financial account created through Financial Accounts for platforms. See [Payouts and topups from Stripe payments](https://docs.stripe.com/financial-accounts/connect/moving-money/payouts.md) for more information.

1. Click **Create Payout**, then go to the **Overview** page to view the transaction details.

### See the code and API logs for these steps

Use the following code samples and API logs to learn more about these steps.

### Receive a payment

You can use payment links to receive a test payment and then transfer the payment balance to the connected account associated Financial Account:

1. Create a `Price` that determines the amount paid to the connected account after payment completes.

   ```javascript
   const prices = await stripe.prices.list(
     {
       limit: 1,
       active: true,
       type: "one_time",
     },
     {
       stripeAccount: "{{CONNECTED_ACCOUNT_ID}}",
     },
   );
   
   const price =
     prices.data.length < 1
       ? await stripe.prices.create(
           {
             unit_amount: 1000,
             currency: "usd",
             product_data: {
               name: "Some Product",
             },
           },
           {
             stripeAccount: "{{CONNECTED_ACCOUNT_ID}}",
           },
         )
       : prices.data[0];
   ```

1. After obtaining the price, the sample app creates a `PaymentLink`, and redirects the user to complete the payment. Use the price `id` from the previous step to set the value for the `price` parameter. Alternatively, you can exclude the parameter to use a default value instead.

   ```javascript
   const paymentLink = await stripe.paymentLinks.create(
     {
       line_items: [
         {
           price: price.id,
           quantity: 1,
           adjustable_quantity: { enabled: true },
         },
       ],
     },
     {
       stripeAccount: "{{CONNECTED_ACCOUNT_ID}}",
     },
   );
   ```

### Payout from the connected account payments balance

[Payouts](https://docs.stripe.com/financial-accounts/connect/moving-money/payouts.md#payouts) can send funds from a connected account’s payments balance to their financial account. Complete the following steps to execute a payout:

1. Check if there’s an external account configured for the connected account. To do so, use the [accounts.retrieve](https://docs.stripe.com/api/accounts/retrieve.md) API to obtain the [account object](https://docs.stripe.com/api/accounts/object.md) and verify if the `external_account` property is populated.

   ```javascript
   const responseAccount = await stripe.accounts.retrieve("{{CONNECTED_ACCOUNT_ID}}");
   
   const hasExternalAccount = responseAccount.external_accounts?.data[0] != undefined;
   ```

1. If there isn’t an existing external account, the user can set up the financial account as the connected account’s external account.

   ```javascript
   const financialAccounts = await stripe.treasury.financialAccounts.list(
     { expand: ["data.financial_addresses.aba.account_number"] },
     {
       stripeAccount: "{{CONNECTED_ACCOUNT_ID}}",
     },
   );
   
   const financialAccount = financialAccounts.data[0];
   const aba = financialAccount.financial_addresses[0]?.aba;
   
   // ...
   
   const token = await stripe.tokens.create(
     {
       bank_account: {
         account_number: aba.account_number,
         country: "US",
         currency: "usd",
         routing_number: aba.routing_number,
       },
     },
     undefined,
   );
   await stripe.accounts.createExternalAccount("{{CONNECTED_ACCOUNT_ID}}", {
     external_account: token.id,
   });
   ```

1. Initiate a payout to the connected account’s external account. In this case, the external account is the financial account. Find the API log: [POST to /v1/payouts](https://dashboard.stripe.com/test/logs?method%5B0%5D=post&path=%2Fv1%2Fpayouts).

   ```javascript
   const balance = await stripe.balance.retrieve(
     {
       stripeAccount: "{{CONNECTED_ACCOUNT_ID}}",
     }
   );
   
   const payout = await stripe.payouts.create(
     {
       amount: balance.available[0].amount,
       currency: 'usd',
     },
     {
       stripeAccount: "{{CONNECTED_ACCOUNT_ID}}",
     }
   );
   ```

View the `treasury.received_credit.created` event on the connect account at *https://dashboard.stripe.com/{{CONNECT\_ACCOUNT\_ID}}/test/events?type=treasury.received\_credit.created*. You can find the connected account’s ID in the response to step 1.


# Copy the sample app

> This is a Copy the sample app for when use-or-copy-sample-app is copy-sample-app. View the full page at https://docs.stripe.com/issuing/sample-app?use-or-copy-sample-app=copy-sample-app.

When you copy the app and use it with your own Stripe API keys, use your Dashboard to:

- View and edit objects you create from the app.
- Follow [API logs](https://dashboard.stripe.com/test/logs) generated by your actions in the sample app.
- Add your logo and colors to configure the app’s onboarding forms.

After you finish copying the sample app, follow the steps in [Use our sample app](https://docs.stripe.com/issuing/sample-app.md?use-or-copy-sample-app=use-sample-app).

## Before you begin 

1. [Register your platform](https://dashboard.stripe.com/connect/tasklist).
1. [Enable Financial Accounts for platforms and Issuing](https://docs.stripe.com/financial-accounts/connect/access.md) in a *sandbox* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes) environment for testing. Your web app won’t work until you complete this step.
1. [Customize brand settings](https://dashboard.stripe.com/settings/connect/stripe-dashboard/branding). Adding a business name, icon, and brand color is required for *Connect* (Connect is Stripe's solution for multi-party businesses, such as marketplace or software platforms, to route payments between sellers, customers, and other recipients) Onboarding.

## Choose how to deploy the app

You can choose to either deploy the app to a shareable web link or copy the source code.

#### Deploy to a shareable web link

Without writing code, you can use Render to get your own unique, public URL (for example, https://issuing-treasury-xyz1.onrender.com).

1. Click **Deploy to Render**, and then complete the signup process to create a free Render account.

   [Deploy to Render](https://render.com/deploy?repo=https://github.com/stripe-samples/issuing-treasury)

1. On the Blueprints screen, enter the following:

   - **Blueprint Name**: Type any name (for example, “Demo”)
   - **Branch**: Select `main`
   - **NEXT\_PUBLIC\_STRIPE\_PUBLISHABLE\_KEY**: Log in to see your publishable API key *(starts `with pk_test`)*
   - **STRIPE\_SECRET\_KEY**: Log in to see your secret API key *(starts with `sk_test`)*

1. Click **Apply**.

1. Wait for Render to finish deploying (which can take up to 5 minutes), then click **issuing-treasury**.
![Your unique URL shown on Render's website](https://b.stripecdn.com/docs-statics-srv/assets/render-create-webservice-issuing-treasury.7fccd99a307610d8ff42bc8f2628bb0c.png)
   
1. On the next page, click your unique URL to open the web app.
![Your unique URL shown on Render's website](https://b.stripecdn.com/docs-statics-srv/assets/issuing-treasury-onrender-url.3624704c9826a8866f8015adea7a9cae.png)

#### Copy the source code

To create test Issuing and Financial Account objects through the web app and view API logs in real time, go to [GitHub](https://github.com/stripe-samples/issuing-treasury). Follow the [README](https://github.com/stripe-samples/issuing-treasury#stripe-issuing-and-treasury-an-embedded-finance-starter-application) to properly copy and configure the sample app as well as [set up Postgres](https://github.com/stripe-samples/issuing-treasury#database-setup) and other components.