Sign in
An image of the Stripe logo
Create account
Sign in
Home
Payments
Business operations
Financial services
Developer tools
No-code
All products
Home
Payments
Business operations
Home
Payments
Business operations
Financial services
Developer tools
Support
Overview
Overview
Global Issuing
Getting Started
How Issuing works
Create cards
Cards
Virtual cards
Physical cards
Testing physical cards
Replacement cards
Digital wallets
Support
Controls
Spending controls
Real-time authorizations
Fraud protection
3D Secure
PIN management
Issuing Elements
Token Management
Funding
Balance
Connect
Purchases
Authorizations
Transactions
Disputes
Testing
Merchant categories
Additional information
Marketing guidance (Europe/UK)
Product and marketing compliance guidance (US)
Issuing
·
HomeFinancial servicesIssuing cards

Issuing real-time authorizations

Learn about real-time authorizations.

Webhooks

Your synchronous webhook is only used for authorization requests. All other notifications are sent to your regular webhook endpoint.

Using the synchronous webhook, you can approve or decline authorization requests in real time.

Your webhook endpoint can be configured in your settings. When a card is used to make a purchase, Stripe creates an issuing_authorization.request and sends it to your configured endpoint for your approval.

Responding to authorization requests

You can respond to authorizations requests by either responding directly to the webhook event (preferred) or by making a separate API call to either approve or decline the request.

Respond directly:

Respond to the issuing_authorization.request webhook event directly to either approve or decline an authorization after it’s received. We recommend this method because it’s the most simple approach.

Webhook response:

Our webhook accepts JSON responses with the following parameters:

Status code: Return 200 to indicate success.

Header:

field name required or optional description
Stripe-VersionrequiredVersion in YYYY-dd-mm format.
Content-TypeoptionalThe only content type accepted for Authorization webhook responses is application/json.

Body:

field name required or optional type description
approvedrequiredBooleanSet true to approve an authorization and false to decline.
amountoptionalIntegerIf the authorization’s pending_request.is_amount_controllable property is true, you can provide this value to control how much to hold for the authorization. It must be positive.
metadataoptionalSet of key-value pairsThis can be useful for storing additional information about the object in a structured format.
server.rb
# Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Set your secret key. Remember to switch to your live secret key in production. # See your keys here: https://dashboard.stripe.com/apikeys Stripe.api_key =
'sk_test_rfaBmNUu1lWB7VZ0MMSIsYjH'
# Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. begin event = Stripe::Webhook.construct_event( payload, sig_header, webhook_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid signature. status 400 return end if event['type'] == 'issuing_authorization.request' auth = event['data']['object'] # ... custom business logic status 200 header 'Stripe-Version' => '2022-08-01', 'Content-Type' => 'application/json' data = { 'approved' => true } body data.to_json end # ...handle other cases end

Make an API call:

Make an API call to either approve or decline the request and include the Authorization ID. If you use this method, your webhook must approve or decline each authorization before responding to the incoming webhook request. We’ll deprecate this method at the end of 2023.

server.rb
# Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Set your secret key. Remember to switch to your live secret key in production. # See your keys here: https://dashboard.stripe.com/apikeys Stripe.api_key =
'sk_test_rfaBmNUu1lWB7VZ0MMSIsYjH'
# Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. begin event = Stripe::Webhook.construct_event( payload, sig_header, webhook_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid signature. status 400 return end if event['type'] == 'issuing_authorization.request' auth = event['data']['object'] handle_authorization(auth) end status 200 end def handle_authorization(auth) # Authorize the transaction authorization = Stripe::Issuing::Authorization.approve(auth["id"]) end

We recommend that you only use one of these two methods to respond to authorization requests. For users migrating from one method to another, both methods are supported during a migration. In the event both methods are used on the same authorization, the API call takes precedence over the direct response. For migrations, we recommend only using one method on a given request at a time.

If Stripe doesn’t receive your approve or decline response or request within 2 seconds, the Authorization is automatically approved or declined based on your timeout settings.

If your Issuing balance has insufficient funds for the incoming authorization, the authorization will be denied and your webhook endpoint will not receive the issuing_authorization.request event. To learn more about funding your Issuing balance, read here.

Authorization requests

When an authorization request is sent to your webhook, the amount requested is stored in pending_request.

{ "id": "iauth_1CmMk2IyNTgGDVfzFKlCm0gU", "object": "issuing_authorization", "approved": false, "amount": 0, "currency": "eur", "status": "pending", ... "pending_request": { "amount": 400, "currency": "eur", "merchant_amount": 360, "merchant_currency": "gbp" } }

The top-level amount in the request is set to 0 and approved is false. Once you respond to the request, the top-level amount reflects the total amount approved or declined, the approved field is updated, and pending_request is set to null.

Testing webhooks locally

To test webhooks locally, you can use Stripe CLI. Once you have it installed, you can forward events to your server:

Command Line
stripe listen --forward-to localhost:4242/webhook Ready! Your webhook signing secret is '{{WEBHOOK_SIGNING_SECRET}}' (^C to quit)

In another terminal, you can then manually trigger issuing_authorization.request events from the CLI for more streamlined testing.

Command Line
stripe trigger issuing_authorization.request

Learn more about setting up webhooks.

Autopilot Beta

Autopilot is a set of fallback options that allow you to continue making real-time authorization decisions in the event your systems are down or don’t respond to an authorization request within the allotted time window.

For users with their own dedicated Bank Identification Numbers (BIN), we also offer Autopilot in the event that Stripe can’t communicate with the network to prevent any continuity issues that might result.

In both cases, we make an authorization decision on your behalf based on a predefined set of rules. We create authorization objects for transmission, so that reconciliation can take place for the Autopilot transactions. When an authorization is approved or declined through Autopilot while you’re down, the request_history.reason field within the issuing_authorization.created webhook changes to webhook_timeout. When an authorization is approved or declined through Autopilot while Stripe is down, the request_history.reason field within the issuing_authorization.created webhook changes to network_stip.

Request early access

Access to Autopilot is currently limited to US beta users. You must be an Issuing customer to join the beta. Contact Stripe for more information.

Was this page helpful?
Questions? Contact us.
Watch our developer tutorials.
Check out our product changelog.
Powered by Markdoc
You can unsubscribe at any time. Read our privacy policy.
On this page
Responding to authorization requests
Authorization requests
Autopilot
Stripe Shell
Test mode
▗▄ ▄▟█ █▀▀ ▗▟████▙▖ ██████ ███▗▟█ ███ ███▗▟██▙▖ ▗▟█████▙▖ ███▖ ▀▀ ███ ███▀▀▀ ███ ███▀ ███ ███ ███ ▝▜████▙▖ ███ ███ ███ ███ ███ █████████ ▄▄ ▝███ ███ ▄ ███ ███ ███▄ ███ ███ ▄▄ ▝▜████▛▘ ▝▜███▛ ███ ███ ███▝▜██▛▘ ▝▜█████▛▘ ███ ▀▘
Welcome to the Stripe Shell! Stripe Shell is a browser-based shell with the Stripe CLI pre-installed. Login to Stripe docs and press Control + Backtick on your keyboard to start managing your Stripe resources in test mode. - View supported commands: - Find webhook events: - Listen for webhook events: - Call Stripe APIs: stripe [api resource] [operation] (e.g. )
The Stripe Shell is best experienced on desktop.
$