Terminal
Connect platforms

Using Terminal with Connect

Integrate Stripe Terminal with your Connect platform.

Stripe Terminal is fully compatible with Stripe Connect, making it easy for your platform or marketplace to accept in-person payments.

The way Terminal creates API objects depends on whether you use direct charges or destination charges. If you use direct charges, all Terminal API objects belong to connected accounts. If you use destination charges, all Terminal API objects are created on your platform account. In both cases, you can use Locations to group readers as you see fit.

Direct charges

With direct charges, API objects belong to the connected account rather than the platform. The connected account is responsible for the cost of Stripe fees, refunds, and chargebacks.

In the Dashboard, you can view your Terminal data by logging in as the connected account.

Creating locations and readers Server-side

With direct charges, payment objects are created belonging to the connected account. Other Terminal API objects like Locations and Readers must be created belonging to the same connected account.

To create a Location belonging to a connected account, use the Stripe-Account header.

curl https://api.stripe.com/v1/terminal/locations \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d display_name=HQ \ -d "address[line1]"="1272 Valencia Street" \ -d "address[city]"="San Francisco" \ -d "address[state]"=CA \ -d "address[country]"=US \ -d "address[postal_code]"=94110 \ -H "Stripe-Account: {CONNECTED_ACCOUNT_ID}"
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' Stripe::Terminal::Location.create({ display_name: 'HQ', address: { line1: '1272 Valencia Street', city: 'San Francisco', state: 'CA', country: 'US', postal_code: '94110', } }, { stripe_account: '{CONNECTED_ACCOUNT_ID}', })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' stripe.terminal.Location.create( display_name= 'HQ', address= { line1: '1272 Valencia Street', city: 'San Francisco', state: 'CA', country: 'US', postal_code: '94110', }, stripe_account='{CONNECTED_ACCOUNT_ID}', )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); \Stripe\Location::create([ 'display_name' => 'HQ', 'address' => [ 'line1' => '1272 Valencia Street', 'city' => 'San Francisco', 'state' => 'CA', 'country' => 'US', 'postal_code' => '94110', ], [ 'stripe_account' => '{CONNECTED_ACCOUNT_ID}', ], ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; LocationCreateParams.Address address = LocationCreateParams.Address.builder() .setLine1("1272 Valencia Street") .setCity("San Francisco") .setState("CA") .setCountry("US") .setPostalCode("94110") .build(); LocationCreateParams params = LocationCreateParams.builder() .setDisplayName("HQ") .setAddress(address) .build(); RequestOptions requestOptions = RequestOptions.builder() .setStripeAccount("{CONNECTED_ACCOUNT_ID}") .build(); Location.create(params, requestOptions);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const location = await stripe.terminal.locations.create({ display_name: 'HQ', address: { line1: '1272 Valencia Street', city: 'San Francisco', state: 'CA', country: 'US', postal_code: '94110', } }, { stripeAccount: '{CONNECTED_ACCOUNT_ID}' });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.TerminalLocationParams{ Address: &stripe.AccountAddressParams{ Line1: stripe.String("1272 Valencia Street"), City: stripe.String("San Francisco"), State: stripe.String("CA"), Country: stripe.String("US"), PostalCode: stripe.String("94110"), }, DisplayName: stripe.String("HQ"), } params.SetStripeAccount("{CONNECTED_ACCOUNT_ID}") l, _ := location.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new LocationCreateOptions { DisplayName = "HQ", Address = new AddressOptions { Line1 = "1272 Valencia Street", City = "San Francisco", State = "CA", Country = "US", PostalCode = "94110", }, }; var requestOptions = new RequestOptions(); requestOptions.StripeAccount = "{CONNECTED_ACCOUNT_ID}"; var service = new LocationService(); service.Create(options, requestOptions);

Before you can connect your application to the Verifone P400, you must register the reader to a Stripe account. To register a reader to a connected account, use the Stripe-Account header. You may also provide a location parameter. If you do not provide a location, the reader is categorized as ungrouped on the connected account.

curl https://api.stripe.com/v1/terminals/readers \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d registration_code="{READER_REGISTRATION_CODE}" \ -d location="{LOCATION_ID}" \ -d label="Alice's Reader" \ -H "Stripe-Account: {CONNECTED_ACCOUNT_ID}"
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' Stripe::Terminal::Reader.create({ registration_code: "{READER_REGISTRATION_CODE}", label: "Alice's Reader", location: "{LOCATION_ID}", }, { stripe_account: "{CONNECTED_ACCOUNT_ID}", })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' stripe.terminal.Reader.create( registration_code="{READER_REGISTRATION_CODE}", label="Alice's Reader", location="{LOCATION_ID}", stripe_account="{CONNECTED_ACCOUNT_ID}", )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); \Stripe\Terminal\Readers::create([ 'registration_code' => "{READER_REGISTRATION_CODE}", 'label' => "Alice's Reader", 'location' => "{LOCATION_ID}", ], [ 'stripe_account' => "{CONNECTED_ACCOUNT_ID}", ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; ReaderCreateParams params = ReaderCreateParams.builder() .setRegistrationCode("{READER_REGISTRATION_CODE}") .setLabel("Alice's Reader") .setLocation("{LOCATION_ID}") .build(); RequestOptions requestOptions = RequestOptions.builder() .setStripeAccount("{CONNECTED_ACCOUNT_ID}") .build(); Reader.create(params, requestOptions);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const reader = await stripe.terminal.readers.create({ registration_code: "{READER_REGISTRATION_CODE}", label: "Alice's Reader", location: "{LOCATION_ID}", }, { stripeAccount: "{CONNECTED_ACCOUNT_ID}" });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.TerminalReaderParams{ Label: stripe.String("Alice's Reader"), Location: stripe.String("{LOCATION_ID}"), RegistrationCode: stripe.String("{READER_REGISTRATION_CODE}"), } params.SetStripeAccount("{CONNECTED_ACCOUNT_ID}") r, _ := reader.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new ReaderCreateOptions { RegistrationCode = "{READER_REGISTRATION_CODE}, Label = "Alice's Reader", Location = "{LOCATION_ID}", }; var requestOptions = new RequestOptions(); requestOptions.StripeAccount = "{CONNECTED_ACCOUNT_ID}"; var service = new ReaderService(); service.Create(options, requestOptions);

Creating connection tokens Server-side

When creating a ConnectionToken for the Terminal SDK, set the Stripe-Account header to the connected account accepting payments. You may also provide a location parameter to control access to readers. If you provide a location, the ConnectionToken is only usable with readers assigned to that location. If you do not provide a location, the ConnectionToken is usable with all readers.

curl https://api.stripe.com/v1/terminal/connection_tokens \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d location="{LOCATION_ID}" \ -H "Stripe-Account: {CONNECTED_ACCOUNT_ID}"
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' Stripe::Terminal::ConnectionToken.create({ location: '{LOCATION_ID}' }, { stripe_account: '{CONNECTED_ACCOUNT_ID}', })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' connection_token = stripe.terminal.ConnectionToken.create( location='{LOCATION_ID}', stripe_account='{CONNECTED_ACCOUNT_ID}', )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); $connectionToken = \Stripe\Terminal\ConnectionToken::create([ 'location' => '{LOCATION_ID}' ], [ 'stripe_account' => '{CONNECTED_ACCOUNT_ID}', ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; ConnectionTokenCreateParams params = ConnectionTokenCreateParams.builder() .setLocation("{LOCATION_ID}") .build(); RequestOptions requestOptions = RequestOptions.builder() .setStripeAccount("{CONNECTED_ACCOUNT_ID}") .build(); ConnectionToken connectionToken = ConnectionToken.create(params, requestOptions);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); let connectionToken = stripe.terminal.connectionTokens.create({ location: '{LOCATION_ID}' }, { stripeAccount: '{CONNECTED_ACCOUNT_ID}' });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.TerminalConnectionTokenParams{ Location: stripe.String("{LOCATION_ID}"), } params.SetStripeAccount("{CONNECTED_ACCOUNT_ID}") ct, _ := connectiontoken.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new ConnectionTokenCreateOptions{}; var service = new ConnectionTokenService( Location = "{LOCATION_ID}" ); var requestOptions = new RequestOptions(); requestOptions.StripeAccount = "{CONNECTED_ACCOUNT_ID}"; var connectionToken = service.Create(options, requestOptions);

Creating Payment Intents Client-side Server-side

With the iOS and Android SDKs, you can create a PaymentIntent on the client or server. The JavaScript SDK only supports server-side creation.

Client-side

When creating a PaymentIntent client-side for direct charges, you don’t need to specify any additional parameters for the PaymentIntent. Instead, when creating a ConnectionToken, set the Stripe-Account header to the connected account accepting payments. The iOS and Android SDK create the PaymentIntent on the same connected account the ConnectionToken belongs to. For more information, see Create Payment Intents Client-side.

Server-side

The JavaScript SDK requires you to create the PaymentIntent on your server. For iOS or Android, you might choose to create the PaymentIntent on your server if the information required to start a payment isn’t readily available in your app. For more information, see Create Payment Intents Server-side.

When creating a PaymentIntent server-side for direct charges, set the Stripe-Account header to the connected account.

curl https://api.stripe.com/v1/payment_intents \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d amount=1000 \ -d currency=usd \ -d "payment_method_types[]"=card_present \ -d capture_method=manual \ -H "Stripe-Account: {CONNECTED_ACCOUNT_ID}"
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' intent = Stripe::PaymentIntent.create({ amount: 1000, currency: 'usd', payment_method_types: ['card_present'], capture_method: 'manual', }, { stripe_account: '{CONNECTED_ACCOUNT_ID}', })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' stripe.PaymentIntent.create( amount=1000, currency='usd', payment_method_types=['card_present'], capture_method='manual', stripe_account='{CONNECTED_ACCOUNT_ID}', )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); \Stripe\PaymentIntent::create([ 'amount' => 1000, 'currency' => 'usd', 'payment_method_types' => ['card_present'], 'capture_method' => 'manual', ], [ 'stripe_account' => '{CONNECTED_ACCOUNT_ID}', ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; PaymentIntentCreateParams params = PaymentIntentCreateParams.builder() .addPaymentMethodType("card_present") .setAmount(1000L) .setCurrency("usd") .setCaptureMethod(PaymentIntentCreateParams.CaptureMethod.MANUAL) .build(); RequestOptions requestOptions = RequestOptions.builder() .setStripeAccount("{CONNECTED_ACCOUNT_ID}") .build(); PaymentIntent.create(params, requestOptions);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const intent = await stripe.paymentIntents.create({ amount: 1000, currency: 'usd', payment_method_types: ['card_present'], capture_method: 'manual', }, { stripeAccount: '{CONNECTED_ACCOUNT_ID}' });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.PaymentIntentParams{ Amount: stripe.Int64(1000), Currency: stripe.String(string(stripe.CurrencyUSD)), PaymentMethodTypes: stripe.StringSlice([]string{ "card_present", }), CaptureMethod: stripe.String("manual"), } params.SetStripeAccount("{CONNECTED_ACCOUNT_ID}") paymentintent.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var service = new PaymentIntentService(); var options = new PaymentIntentCreateOptions { Amount = 1000, Currency = "usd", PaymentMethodTypes = new List<string> { "card_present" }, CaptureMethod = "manual", }; var requestOptions = new RequestOptions(); requestOptions.StripeAccount = "{CONNECTED_ACCOUNT_ID}"; service.Create(options, requestOptions);

Destination charges

When using destination charges, payment objects are created on your connected accounts but belong to your platform account. Each payment creates a transfer to a connected account automatically.

In the Dashboard, you can view your Terminal data directly when logged into your platform account.

Creating locations and readers Server-side

With destination charges, payment objects are created on your platform account, and then funds get transferred to the correct connected account. Similarly, Terminal API objects get created on your platform account, even though they belong to connected accounts.

The best way to group Reader objects by connected account is by assigning them to locations. To create a Location for a connected account, use a display name that identifies the account.

curl https://api.stripe.com/v1/terminal/locations \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d display_name="{CONNECTED_ACCOUNT_NAME}" \ -d "address[line1]"="1272 Valencia Street" \ -d "address[city]"="San Francisco" \ -d "address[state]"=CA \ -d "address[country]"=US \ -d "address[postal_code]"=94110
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' Stripe::Terminal::Location.create({ display_name: '{CONNECTED_ACCOUNT_NAME}', address: { line1: '1272 Valencia Street', city: 'San Francisco', state: 'CA', country: 'US', postal_code: '94110', } })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' stripe.terminal.Location.create( display_name= '{CONNECTED_ACCOUNT_NAME}', address= { line1: '1272 Valencia Street', city: 'San Francisco', state: 'CA', country: 'US', postal_code: '94110', } )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); \Stripe\Location::create([ 'display_name' => '{CONNECTED_ACCOUNT_NAME}', 'address' => [ 'line1' => '1272 Valencia Street', 'city' => 'San Francisco', 'state' => 'CA', 'country' => 'US', 'postal_code' => '94110', ], ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; LocationCreateParams.Address address = LocationCreateParams.Address.builder() .setLine1("1272 Valencia Street") .setCity("San Francisco") .setState("CA") .setCountry("US") .setPostalCode("94110") .build(); LocationCreateParams params = LocationCreateParams.builder() .setDisplayName("{CONNECTED_ACCOUNT_NAME}") .setAddress(address) .build(); Location.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const location = await stripe.terminal.locations.create({ display_name: '{CONNECTED_ACCOUNT_NAME}', address: { line1: '1272 Valencia Street', city: 'San Francisco', state: 'CA', country: 'US', postal_code: '94110', } })
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.TerminalLocationParams{ Address: &stripe.AccountAddressParams{ Line1: stripe.String("1272 Valencia Street"), City: stripe.String("San Francisco"), State: stripe.String("CA"), Country: stripe.String("US"), PostalCode: stripe.String("94110"), }, DisplayName: stripe.String("{CONNECTED_ACCOUNT_NAME}"), } l, _ := location.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new LocationCreateOptions { DisplayName = "{sample_location.display_name}", Address = new AddressOptions { Line1 = "1272 Valencia Street", City = "San Francisco", State = "CA", Country = "US", PostalCode = "94110", }, }; var service = new LocationService(); service.Create(options);

Before you can connect your application to the Verifone P400, you must register the reader to your platform account. To group readers by connected account, you must also provide a location parameter. If you don’t provide a location, the reader is categorized as ungrouped on your platform account.

curl https://api.stripe.com/v1/terminals/readers \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d registration_code="{READER_REGISTRATION_CODE}" \ -d location="{LOCATION_ID}" \ -d label="Alice's Reader"
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' Stripe::Terminal::Reader.create({ registration_code: "{READER_REGISTRATION_CODE}", label: "Alice's Reader", location: "{LOCATION_ID}", })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' stripe.terminal.Reader.create( registration_code="{READER_REGISTRATION_CODE}", label="Alice's Reader", location="{LOCATION_ID}", )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); \Stripe\Terminal\Readers::create([ 'registration_code' => "{READER_REGISTRATION_CODE}", 'label' => "Alice's Reader", 'location' => "{LOCATION_ID}", ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; ReaderCreateParams params = ReaderCreateParams.builder() .setRegistrationCode("{READER_REGISTRATION_CODE}") .setLabel("Alice's Reader") .setLocation("{LOCATION_ID}") .build(); Reader.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const reader = await stripe.terminal.readers.create({ registration_code: "{READER_REGISTRATION_CODE}", label: "Alice's Reader", location: "{LOCATION_ID}", });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.TerminalReaderParams{ Label: stripe.String("Alice's Reader"), Location: stripe.String("{LOCATION_ID}"), RegistrationCode: stripe.String("{READER_REGISTRATION_CODE}"), } r, _ := reader.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new ReaderCreateOptions { RegistrationCode = "{READER_REGISTRATION_CODE}, Label = "Alice's Reader", Location = "{LOCATION_ID}", }; var service = new ReaderService(); service.Create(options);

Creating connection tokens Server-side

When creating a ConnectionToken for the Terminal SDK, use your platform account’s secret key. Do not set the Stripe-Account header. Provide a location parameter to control access to readers. If you provide a location, the ConnectionToken is only usable with readers assigned to that location. If you do not provide a location, the ConnectionToken is usable with all readers.

curl https://api.stripe.com/v1/terminal/connection_tokens \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d location="{LOCATION_ID}"
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' Stripe::Terminal::ConnectionToken.create({ location: '{LOCATION_ID}' })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' connection_token = stripe.terminal.ConnectionToken.create( location='{LOCATION_ID}' )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); let connectionToken = stripe.terminal.connectionTokens.create({ location: '{LOCATION_ID}' });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); $connectionToken = \Stripe\Terminal\ConnectionToken::create([ 'location' => '{LOCATION_ID}' ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; ConnectionTokenCreateParams params = ConnectionTokenCreateParams.builder() .setLocation("{LOCATION_ID}") .build(); ConnectionToken connectionToken = ConnectionToken.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.TerminalConnectionTokenParams{ Location: stripe.String("{LOCATION_ID}"), } ct, _ := connectiontoken.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new ConnectionTokenCreateOptions{}; var service = new ConnectionTokenService( Location = "{LOCATION_ID}" ); var connectionToken = service.Create(options);

Creating Payment Intents Client-side Server-side

When creating a PaymentIntent using destination charges, provide the on_behalf_of and transfer_data[destination], and application_fee_amount parameters.

The on_behalf_of parameter is the ID of the connected account that will become the settlement merchant for the payment. For Terminal transactions, this parameter must be set in cases where the platform country is not the same as the Connect account country. When on_behalf_of is set, Stripe automatically:

  • Settles charges in the country of the specified account, thereby minimizing declines and avoiding currency conversions
  • Uses the fee structure for the connected account’s country
  • Lists the connected account’s address and phone number on the customer’s credit card statement, as opposed to the platform’s address and phone number (only occurs if the account and platform are in different countries)

For transfer_data[destination], set the ID of the connected account that should receive the transfer.

Finally, you may withhold an application fee for your platform by providing the application_fee_amount parameter.

Client-side

With the iOS and Android SDKs, you can create a PaymentIntent client-side and provide the onBehalfOf, transferDataDestination, and applicationFeeAmount parameters.

import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() { let params = PaymentIntentParameters(amount: 1000, currency: "usd") params.onBehalfOf = "{CONNECTED_ACCOUNT_ID}" params.transferDataDestination = "{CONNECTED_ACCOUNT_ID}" params.applicationFeeAmount = 200 Terminal.shared.createPaymentIntent(params) { createResult, createError in if let error = createError { print("createPaymentIntent failed: (error)") } else if let paymentIntent = createResult { print("createPaymentIntent succeeded") // ... } } } // ... }
#import "APPPaymentViewController.h" #import <StripeTerminal/StripeTerminal.h> @implementation APPPaymentViewController // Action for a "Checkout" button - (void)checkoutAction { SCPPaymentIntentParameters *params = [[SCPPaymentIntentParameters alloc] initWithAmount:1000 currency:@"usd"]; params.onBehalfOf = @"{CONNECTED_ACCONT_ID}"; params.transferDataDestination = @"{CONNECTED_ACCONT_ID}"; params.applicationFeeAmount = @(200); [[SCPTerminal shared] createPaymentIntent:params completion:^(SCPPaymentIntent *createResult, NSError *createError) { if (createError) { NSLog(@"createPaymentIntent failed: %@", createError); } else { NSLog(@"createPaymentIntent succeeded"); // ... } } // ... @end
PaymentIntentParameters params = new PaymentIntentParameters.Builder() .setAmount(1000) .setCurrency("usd") .setOnBehalfOf("{CONNECTED_ACCOUNT_ID}") .setTransferDataDestination("{CONNECTED_ACCOUNT_ID}") .setApplicationFeeAmount(200) .build(); Terminal.getInstance().createPaymentIntent(params, new PaymentIntentCallback() { @Override public void onSuccess(PaymentIntent paymentIntent) { // Placeholder for collecting a payment method with paymentIntent } @Override public void onFailure(TerminalException exception) { // Placeholder for handling exception } } })
val params = PaymentIntentParameters.Builder() .setAmount(100) .setCurrency("usd") .setOnBehalfOf("{CONNECTED_ACCOUNT_ID}") .setTransferDataDestination("{CONNECTED_ACCOUNT_ID}") .setApplicationFeeAmount(200) .build(); Terminal.getInstance().createPaymentIntent(params, object: PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { // Placeholder for collecting a payment method with paymentIntent } override fun onFailure(exception: TerminalException) { // Placeholder for handling exception } })

Server-side

The JavaScript SDK requires you to create the PaymentIntent on your server. For iOS or Android, you might choose to create the PaymentIntent on your server if the information required to start a payment isn’t readily available in your app. For more information, see Create Payment Intents Server-side.

curl https://api.stripe.com/v1/payment_intents \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d amount=1000 \ -d currency=usd \ -d "payment_method_types[]"=card_present \ -d capture_method=manual \ -d application_fee_amount=200 \ -d on_behalf_of="{CONNECTED_ACCOUNT_ID}" \ -d "transfer_data[destination]"="{CONNECTED_ACCOUNT_ID}"
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' intent = Stripe::PaymentIntent.create({ amount: 1000, currency: 'usd', payment_method_types: ['card_present'], capture_method: 'manual', application_fee_amount: 200, on_behalf_of: '{CONNECTED_ACCOUNT_ID}', transfer_data: { destination: '{CONNECTED_ACCOUNT_ID}', }, })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' stripe.PaymentIntent.create( amount=1000, currency='usd', payment_method_types=['card_present'], capture_method='manual', application_fee_amount=200, on_behalf_of='{CONNECTED_ACCOUNT_ID}', transfer_data={ destination: '{CONNECTED_ACCOUNT_ID}', }, )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); \Stripe\PaymentIntent::create([ 'amount' => 1000, 'currency' => 'usd', 'payment_method_types' => ['card_present'], 'capture_method' => 'manual', 'application_fee_amount' => 200, 'on_behalf_of' => '{CONNECTED_ACCOUNT_ID}', 'transfer_data' => [ 'destination' => '{CONNECTED_ACCOUNT_ID}', ], ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; PaymentIntentCreateParams params = PaymentIntentCreateParams.builder() .addPaymentMethodType("card_present") .setAmount(1000L) .setCurrency("usd") .setCaptureMethod(PaymentIntentCreateParams.CaptureMethod.MANUAL) .setApplicationFeeAmount(200L) .setOnBehalfOf("{CONNECTED_ACCOUNT_ID}") .setTransferData( SessionCreateParams.PaymentIntentData.TransferData.builder() .setDestination("{CONNECTED_ACCOUNT_ID}") .build()) .build(); PaymentIntent.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const intent = await stripe.paymentIntents.create({ amount: 1000, currency: 'usd', payment_method_types: ['card_present'], capture_method: 'manual', application_fee_amount: 200, on_behalf_of: '{CONNECTED_ACCOUNT_ID}', transfer_data: { destination: '{CONNECTED_ACCOUNT_ID}', }, });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.PaymentIntentParams{ Amount: stripe.Int64(1000), Currency: stripe.String(string(stripe.CurrencyUSD)), PaymentMethodTypes: stripe.StringSlice([]string{ "card_present", }), CaptureMethod: stripe.String("manual"), ApplicationFeeAmount: stripe.Int64(200), OnBehalfOf: stripe.String("{CONNECTED_ACCOUNT_ID}"), TransferData: &stripe.CheckoutSessionPaymentIntentDataTransferDataParams{ Destination: stripe.String("{CONNECTED_ACCOUNT_ID}"), }, } paymentintent.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var service = new PaymentIntentService(); var options = new PaymentIntentCreateOptions { Amount = 1000, Currency = "usd", PaymentMethodTypes = new List<string> { "card_present" }, CaptureMethod = "manual", ApplicationFeeAmount = 200, OnBehalfOf = "{CONNECTED_ACCOUNT_ID}", TransferData = new SessionPaymentIntentDataTransferDataOptions{ Destination = "{CONNECTED_ACCOUNT_ID}", }, }; service.Create(options);

Next steps

Congratulations! Your Connect platform is now set up to accept in-person payments with Terminal. Next, configure the customer-facing checkout experience in your app, or test your current integration with a physical reader.

Was this page helpful?
Questions? Contact us.
Developer tutorials on YouTube.