Skip to content
Create account or Sign in
/
Ask AI
Create accountSign in
Get started
Payments
Revenue
Platforms and marketplaces
Money management
Developer resources
APIs & SDKsHelp
Overview
Get started with Connect
Design your integration
Integration fundamentals
Example integrations
Account management
Onboard connected accounts
Configure account Dashboards
Capabilities and information requirements
Work with connected account types
Payment processing
Accept payments
Pay out to accounts
Platform administration
Manage your Connect platform
Tax forms for your Connect platform
Embedded finance
Treasury for platforms
Issuing
    Overview
    How Issuing works
    Global availability
    Product and marketing compliance guidance (US)
    Marketing guidance (Europe/UK)
    Manage fraud
    Get started with Issuing
    Onboarding overview
    Choose a cardholder type
    Choose your card type
    Virtual cards
    Physical cards
    Fund your Issuing balance
    Testing
    Integrate Issuing
    Integration guides
    Sample app
    Manage cards
    Digital wallets
    Replacement cards
    Card programs
    Program management
    Processor-only Issuing
    Customize your card program
    Add funds to your card program
    Consumer Credit Issuing
    Consumer prepaid debit cards
    Stablecoin-backed cards
    Controls
    Spending controls
    Lifecycle controls
    Radar
    3DS
    Alerts for updated phone numbers
    Fraud challenges
    Real-time authentications
    Real-time authorizations
      Quickstart
      Migrate to direct webhook response
    Issuer-app authentications
    PIN management
    Issuing Elements
    Token management
    Postfunding
    Postfund your integration with Stripe
    Postfund your integration with Dynamic Reserves
    Purchases
    Authorizations
    Transactions
    Disputes
    Merchant categories
    ATM usage
    Enriched merchant data
    Issuing with Connect
    Set up an Issuing and Connect integration
    Update terms of service acceptance
    Connect funding
    Connected accounts, cardholders, and cards
    Inactive connected accounts offboarding
    Embed card management UI
    Issuing with Connect and Accounts V2 APIs
    Set up an Issuing and Connect integration
    Credit
    Overview
    Set up connected accounts
    Manage credit terms
    Report other credit decisions and manage AANs
    Report required regulatory data for credit decisions
    Manage account obligations
    Test credit integration
    Additional information
    Customer support for Issuing and Treasury for platforms
    Issuing watchlist
Capital for platforms
Managed support
United States
English (United States)
  1. Home/
  2. Platforms and marketplaces/
  3. Issuing

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. Monitor your webhook responses to ensure integration health.

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.

Get started with our interactive guide to real-time authorizations.

Responding to authorization requests

You can respond to authorization requests by responding directly to the webhook event.

Respond directly

Respond to the issuing_authorization.request webhook event directly to either approve or decline an authorization after it’s received.

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-VersionrequiredSee API Versioning for supported values.
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.
send_fraud_challenges Public previewoptionalArray of stringsYou can send a fraud challenge for this authorization only through SMS. Leave it blank if you don’t want to send a challenge.
server.rb
Ruby
Python
PHP
Node.js
Java
Go
.NET
No results
# Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('sk_test_BQokikJOvBiI2HlWgH4olfQ2') # 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' => '2025-03-31.basil', 'Content-Type' => 'application/json' data = { 'approved' => true } body data.to_json end # ...handle other cases end

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

Note

If your Issuing balance has insufficient funds for the incoming authorization, the authorization will be denied and your webhook endpoint won’t 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": "usd", "status": "pending", ... "pending_request": { "amount": 400, "currency": "usd", "merchant_amount": 360, "merchant_currency": "gbp" } }

The top-level amount in the request is set to 0 and approved is false. After 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. After you install it, 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.

Monitor your webhook responses

Monitor your webhook responses for timeouts and errors by subscribing to the issuing_authorization.created and issuing_authorization.updated webhook events. When the request_history.reason property is either webhook_error or webhook_timeout, Stripe isn’t receiving your responses. Don’t rely on approved to gauge integration health because Autopilot can approve on your behalf during an error condition. For example, investigate if an authorization has approved: true but request_history.reason: webhook_error. We surface detailed error messages in the request_history.reason_message field.

Autopilot Public preview

Autopilot provides fallback options that allow you to continue making real-time authorization decisions when your systems are down, don’t respond to an authorization request, or provide an invalid response.

Autopilot makes an authorization decision on your behalf based on a predefined set of rules. We create Authorization objects for transmission to reconcile Autopilot transactions. When Autopilot approves or declines an authorization, the request_history.reason property of the issuing_authorization.created webhook is either webhook_error or webhook_timeout:

  • webhook_error if you respond to the real-time authorization webhook with an invalid Stripe API version in the request headers, or if we can’t process your response.
  • webhook_timeout for all other failure modes.

To configure Autopilot, contact Stripe support, and monitor.

Stripe Autopilot Public preview

For users with their own dedicated Bank Identification Numbers (BIN), Stripe Autopilot can help make authorization decisions when the card network can’t reach Stripe.

When an authorization is approved or declined through Stripe Autopilot while Stripe is down, the request_history.reason property of the issuing_authorization.created webhook is network_fallback.

In some cases, Stripe declines an authorization but can’t communicate with the card network, and the network approves the authorization. When that happens, Stripe doesn’t hold the authorized funds, but they might still be captured.

To configure Stripe Autopilot, contact Stripe support, and monitor.

Fraud challenges through webhooks Public preview

Fraud challenges allow your cardholders to retry non-fraudulent transactions that would have otherwise been blocked. While fraud challenges are generally available, the ability to trigger them yourself through real-time webhook responses is in public preview.

To manage the rules that dictate when a fraud challenge is sent, adjust your response to the issuing_authorization.request webhook. You can trigger fraud challenges in scenarios where you detect spending that appears suspicious and want additional verification (for example, a cardholder using their card out of the country).

To do so, decline the issuing_authorization.request webhook and include the send_fraud_challenges field with the ["sms"] value.

Triggering fraud challenges through real-time webhook responses is currently limited to preview users. You must be an Issuing customer to join the preview. To request access to the preview, log in to your Stripe account and refresh the page. Contact Stripe for more information.

Was this page helpful?
YesNo
  • Need help? Contact Support.
  • Chat with Stripe developers on Discord.
  • Check out our changelog.
  • Questions? Contact Sales.
  • LLM? Read llms.txt.
  • Powered by Markdoc
On this page