# Issuing and Treasury 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 Treasury 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 ![The Issuing and Treasury demo app's Card details page](images/financial-services/issuing-treasury-demo-app.png) The Issuing and Treasury sample app’s card details page 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 original doc at https://docs.stripe.com/baas/start-integration/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 original doc at https://docs.stripe.com/baas/start-integration/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 original doc at https://docs.stripe.com/baas/start-integration/sample-app?use-or-copy-sample-app=use-sample-app. ## Create an account with 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. ### (Optional) Simulate hosted onboarding to provide full account details 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/treasury/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/design-an-integration.md?connect-onboarding-surface=api&connect-dashboard-type=none&connect-economic-model=buy-rate&connect-loss-liability-owner=platform&connect-charge-type=direct) 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 Stripe Treasury [financial account](https://docs.stripe.com/treasury/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: "<>", 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/<>/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/treasury/moving-money/financial-accounts/into/received-credits.md) (an incoming ACH) for 500 USD, and appears in the [transaction receipt](https://docs.stripe.com/treasury/moving-money/regulatory-receipts.md). 1. Go to the **Financial account** page to [view your account number](https://docs.stripe.com/treasury/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 Treasury 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: "<>", network: "ach", }, { stripeAccount: "<>" } ); ``` ## 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/treasury/moving-money/financial-accounts/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/treasury/moving-money/financial-accounts/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 Stripe Treasury `OutboundPayment` feature. You can use [OutboundPayments](https://docs.stripe.com/treasury/moving-money/financial-accounts/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: "<>", 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: "<>", } ); ``` ### 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/treasury/moving-money/financial-accounts/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( <>, ); ``` ## 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: "<>", } ); ``` ### 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: <>, currency: 'usd', type: 'virtual', status: 'active', }, { stripeAccount: "<>" }, ); ``` ### 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*). ## 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`. When you [copy the sample app](https://docs.stripe.com/baas/start-integration/sample-app.md?use-or-copy-sample-app=use-sample-app) and use it with your own Stripe API keys, you can use your 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( <>, { 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/<>/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'` ## 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 Treasury. See [Payouts and topups from Stripe payments](https://docs.stripe.com/treasury/moving-money/payouts.md) for more information. 1. Click **Create Payout**, then navigate 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: "<>", }, ); const price = prices.data.length < 1 ? await stripe.prices.create( { unit_amount: 1000, currency: "usd", product_data: { name: "Some Product", }, }, { stripeAccount: "<>", }, ) : 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: "<>", }, ); ``` ### Payout from the connected account payments balance [Payouts](https://docs.stripe.com/treasury/moving-money/payouts.md#payouts) can send funds from a connected account’s payments balance to their Treasury 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("<>"); const hasExternalAccount = responseAccount.external_accounts?.data[0] != undefined; ``` 1. If there isn’t an existing external account, the user can set up the Treasury 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: "<>", }, ); 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("<>", { external_account: token.id, }); ``` 1. Initiate a payout to the connected account’s external account. In this case, the external account is the Treasury 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: "<>", } ); const payout = await stripe.payouts.create( { amount: balance.available[0].amount, currency: 'usd', }, { stripeAccount: "<>", } ); ``` 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 original doc at https://docs.stripe.com/baas/start-integration/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/baas/start-integration/sample-app.md?use-or-copy-sample-app=use-sample-app). ## Before you begin ## Choose how to deploy the app You can choose to either deploy the app to a shareable web link or copy the source code. 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 1. On the Blueprints screen, enter the following: 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](images/treasury/render-create-webservice-issuing-treasury.png) 1. On the next page, click your unique URL to open the web app. ![Your unique URL shown on Render's website](images/treasury/issuing-treasury-onrender-url.png) To create test Issuing and Treasury 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.