Issued Card Authorizations Invite Only

     

    Handle authorization requests made during a card purchase.

    When an active card is used to make a purchase, an authorization request is made. This request must be approved for the purchase to be successfully completed. If it’s not, the purchase is declined. You can configure an authorization endpoint and handle authorization requests yourself for complete control, allow Stripe to approve or decline authorizations automatically using authorization controls, or use a combination of both.

    When the authorization request is received, an Authorization object is created. Stripe first checks if you have applied any authorization controls to the card that should decline the request. If the purchase isn’t declined at this point and you have configured an authorization endpoint to handle authorization requests, we send an issuing_authorization.request event to your integration so it can approve or decline the request.

    If no authorization controls declined the request and no endpoint is configured, Stripe approves the authorization. The entire process takes only a few seconds to complete, and occurs while the cardholder and business wait for the response.

    Authorization status changes

    Once an authorization request is approved, the Authorization object’s status is updated to pending, and the issuing_authorization.updated webhook event is sent. The authorized amount is deducted from your account balance and held reserve until the authorization is either captured or voided. Once captured, the Authorization object’s status transitions to closed, and a new transaction is created.

    If the authorization request is declined, its status is immediately set to closed. If it’s voided or not captured in a timely manner, its status transitions to reversed.

    Setting authorization controls

    You can set authorization_controls on cards and cardholders that act as spending rules, giving you some control over how your cards can be used. Authorization controls support spending limits (eg. $100/auth, $3,000/month), blocking types of businesses (eg. bakeries, gambling), and advanced combinations of rules. Although optional, we recommend you specify controls — else all transactions will be approved by default, provided your balance has sufficient funds.

    Authorization controls are optional and can be set when you create new cards and cardholders, or update existing ones at any time.

    field type description
    allowed_categories array Array of strings containing categories of authorizations to always allow.
    blocked_categories array Array of strings containing categories of authorizations to always decline.
    spending_limits array Array of hashes that specify amount-based rules.

    Spending limits

    To limit the amount of money that can be spent, set spending_limits within authorization_controls to an array of hashes with the following structure:

    field type description
    amount integer Maximum amount allowed, in the currency of the card. Amounts in different currencies are converted to the card’s currency when evaluating this control ($10 = 1000).
    interval array The time interval in which the amount applies. Can be per_authorization, daily, weekly, monthly, yearly, or all_time.
    categories array (optional) Array of strings containing categories to apply this limit. Leaving this blank will apply the limit to all authorizations.

    Spending limits can only approve or reject authorizations, and not follow-on charges like tips or hotel fees. In addition, spending totals are summed by their calendar date: months begin on the 1st, weeks on Monday, and days at midnight UTC. This can result in singular transactions spread across multiple time intervals. For example, if a $200 authorization is approved on the 30th of April, and a follow on tip of $40 is charged on the 1st of May, $200 will be counted towards April and $40 will be counted towards May.

    Examples

    The following examples demonstrate different uses of authorization controls for cards and cardholders.

    Limit a cardholder's monthly spending across all their cards

    curl https://api.stripe.com/v1/issuing/cardholders/ich_1Cm3paIyNTgGDVfzBqq1uqxR \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d authorization_controls[spending_limits][0][amount]=300000 \
      -d authorization_controls[spending_limits][0][interval]=monthly
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    Stripe::Issuing::Cardholder.update(
      'ich_1Cm3paIyNTgGDVfzBqq1uqxR',
      {
        authorization_controls: {
          spending_limits: [{
            amount: 300000,
            interval: 'monthly',
          }]
        },
      }
    )
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    stripe.issuing.Cardholder.modify(
      'ich_1Cm3paIyNTgGDVfzBqq1uqxR',
      authorization_controls={
        'spending_limits': [{
          'amount': 300000,
          'interval': 'monthly',
        }]
      }
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    \Stripe\Issuing\Cardholder::update(
      'ich_1Cm3paIyNTgGDVfzBqq1uqxR',
      [
        'authorization_controls' => [
          'spending_limits' => [{
            'amount' => 300000,
            'interval' => 'monthly',
          }]
        ],
      ]
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Cardholder cardholder = Cardholder.retrieve("ich_1Cm3paIyNTgGDVfzBqq1uqxR");
    
    Map<String, Object> spendingLimitParam = new HashMap<String, Object>();
    spendingLimitParam.put("amount", 300000);
    spendingLimitParam.put("interval", "monthly");
    
    List<Map<String, Object>> spendingLimits = new ArrayList<Map<String, Object>>();
    spendingLimits.add(0, spendingLimitParam);
    
    Map<String, Object> controlParams = new HashMap<String, Object>();
    controlParams.put("spending_limits", spendingLimits);
    
    Map<String, Object> params = new HashMap<>();
    params.put("authorization_controls", controlParams);
    
    cardholder.update(params);
    
    // Set your secret key: remember to change this 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 cardholder = stripe.issuing.cardholders.update('ich_1Cm3paIyNTgGDVfzBqq1uqxR', {
      authorization_controls: {
        spending_limits: [{
          amount: 300000,
          interval: 'monthly'
        }],
      },
    );
    

    Limit the spending and allowed categories for a card

    curl https://api.stripe.com/v1/issuing/cards/ic_1Cm3paIyNTgGDVfzBqq1uqxR \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d authorization_controls[allowed_categories][0]=automated_fuel_dispensers \
      -d authorization_controls[spending_limits][0][amount]=8000 \
      -d authorization_controls[spending_limits][0][interval]=per_authorization
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    Stripe::Issuing::Card.update(
      'ic_1Cm3paIyNTgGDVfzBqq1uqxR',
      {
        authorization_controls: {
          allowed_categories: ['automated_fuel_dispensers'],
          spending_limits: [{
            amount: 8000,
            interval: 'per_authorization'
          }]
        },
      }
    )
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    stripe.issuing.Card.modify(
      'ic_1Cm3paIyNTgGDVfzBqq1uqxR',
      authorization_controls={
        'allowed_categories': ['automated_fuel_dispensers'],
        'spending_limits': [{
          'amount': 8000,
          'interval': 'per_authorization'
        }]
      }
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    \Stripe\Issuing\Card::update(
      'ic_1Cm3paIyNTgGDVfzBqq1uqxR',
      [
        'authorization_controls' => [
          'allowed_categories' => ['automated_fuel_dispensers'],
          'spending_limits' => [
            'amount' => 8000,
            'interval' => 'per_authorization'
          ]
        ],
      ]
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Card card = Card.retrieve("ic_1Cm3paIyNTgGDVfzBqq1uqxR");
    
    Map<String, Object> spendingLimitParam = new HashMap<String, Object>();
    spendingLimitParam.put("amount", 8000);
    spendingLimitParam.put("interval", "per_authorization");
    
    List<Map<String, Object>> spendingLimits = new ArrayList<Map<String, Object>>();
    spendingLimits.add(spendingLimitParam);
    
    List<String> allowedCategories = new ArrayList<String>();
    allowedCategories.add("automated_fuel_dispensers");
    
    Map<String, Object> controlParams = new HashMap<String, Object>();
    controlParams.put("allowed_categories", allowedCategories);
    controlParams.put("spending_limits", spendingLimits);
    
    Map<String, Object> params = new HashMap<>();
    params.put("authorization_controls", controlParams);
    
    card.update(params);
    
    // Set your secret key: remember to change this 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 card = stripe.issuing.cards.update('ic_1Cm3paIyNTgGDVfzBqq1uqxR', {
      authorization_controls: {
        allowed_categories: ['automated_fuel_dispensers'],
        spending_limits: [{
          amount: 8000,
          interval: 'per_authorization'
        }]
      },
    );
    

    Restrict a card's weekly spending for certain categories

    curl https://api.stripe.com/v1/issuing/cards/ic_1Cm3paIyNTgGDVfzBqq1uqxR \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d authorization_controls[spending_limits][0][amount]=4000 \
      -d authorization_controls[spending_limits][0][interval]=weekly \
      -d authorization_controls[spending_limits][0][categories][0]=fast_food_restaurants
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    Stripe::Issuing::Card.update(
      'ic_1Cm3paIyNTgGDVfzBqq1uqxR',
      {
        authorization_controls: {
          spending_limits: [{
            amount: 4000,
            interval: 'weekly',
            categories: ['fast_food_restaurants']
          }]
        },
      }
    )
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    stripe.issuing.Card.modify(
      'ic_1Cm3paIyNTgGDVfzBqq1uqxR',
      authorization_controls={
        'spending_limits': [{
          'amount': 4000,
          'interval': 'weekly',
          'categories': ['fast_food_restaurants']
        }]
      }
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    \Stripe\Issuing\Card::update(
      'ic_1Cm3paIyNTgGDVfzBqq1uqxR',
      [
        'authorization_controls' => [
          'spending_limits' => [
            'amount': 4000,
            'interval': 'weekly',
            'categories': ['fast_food_restaurants']
          ]
        ],
      ]
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Card card = Card.retrieve("ic_1Cm3paIyNTgGDVfzBqq1uqxR");
    
    List<String> spendingLimitCategories = new ArrayList<String>();
    spendingLimitCategories.put("fast_food_restaurants");
    
    Map<String, Object> spendingLimitParam = new HashMap<String, Object>();
    spendingLimitParam.put("amount", 8000);
    spendingLimitParam.put("interval", "per_authorization");
    spendingLimitParam.put("categories", spendingLimitCategories);
    
    List<Map<String, Object>> spendingLimits = new ArrayList<Map<String, Object>>();
    spendingLimits.add(spendingLimitParam);
    
    Map<String, Object> controlParams = new HashMap<String, Object>();
    controlParams.put("spending_limits", spendingLimits);
    
    Map<String, Object> params = new HashMap<>();
    params.put("authorization_controls", controlParams);
    
    card.update(params);
    
    // Set your secret key: remember to change this 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 card = stripe.issuing.cards.update('ic_1Cm3paIyNTgGDVfzBqq1uqxR', {
      authorization_controls: {
        spending_limits: [{
          amount: 4000,
          interval: 'weekly',
          categories: ['fast_food_restaurants']
        }]
      },
    );
    

    Using your integration to handle authorization requests

    You can specify an authorization endpoint in your Issuing settings to receive real-time notifications of authorization requests. Once configured, Stripe sends issuing_authorization.request events any time an authorization request is received. This event contains an Authorization object with information about the authorization request, such as the amount, card used, and business information (merchant_data).

     {
      "id": "iauth_1CmMk2IyNTgGDVfzFKlCm0gU",
      "object": "issuing_authorization",
      "approved": true,
      "authorization_method": "online",
      "authorized_amount": 500,
      "authorized_currency": "usd",
      "balance_transactions": [
      ],
      "card": {
    See all 96 lines "id": "ic_1Cm3paIyNTgGDVfzBqq1uqxR", "object": "issuing.card", "authorization_controls": { "allowed_categories": null, "blocked_categories": null, "currency": "usd", "max_amount": 10000, "max_approvals": 1 }, "billing": { "address": { "city": "San Francisco", "country": "US", "line1": "1234 Main Street", "postal_code": "94111", "state": "CA" } }, "brand": "Visa", "cardholder": { "id": "ich_1Cm3pZIyNTgGDVfzI83rasFP", "object": "issuing.cardholder", "billing": { "address": { "city": "San Francisco", "country": "US", "line1": "1234 Main Street", "postal_code": "94111", "state": "CA" }, "name": "Jenny Rosen" }, "created": 1531159885, "email": "jenny.rosen@example.com", "livemode": false, "metadata": { }, "name": "Jenny Rosen", "phone_number": "+18008675309", "status": "active", "type": "individual" }, "created": 1531159886, "currency": "usd", "exp_month": 8, "exp_year": 2019, "last4": "4242", "livemode": false, "metadata": { }, "name": "Jenny Rosen", "shipping": null, "status": "active", "type": "physical" }, "cardholder": null, "created": 1531232578, "held_amount": 700, "held_currency": "usd", "livemode": false, "merchant_data": { "category": "taxicabs_limousines", "city": "San Francisco", "country": "US", "name": "Rocket Rides", "network_id": "1234567890", "postal_code": "94107", "state": "CA" }, "metadata": { }, "pending_authorized_amount": 0, "pending_held_amount": 0, "request_history": [ ], "status": "pending", "transactions": [ ], "verification_data": { "address_line1_check": "not_provided", "address_zip_check": "match", "cvc_check": "match" } }

    Your integration then makes a separate API call to either approve or decline the request, which includes the Authorization object’s ID.

    curl https://api.stripe.com/v1/issuing/authorizations/iauth_1CmMk2IyNTgGDVfzFKlCm0gU/approve \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc:
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    authorization = Stripe::Issuing::Authorization.approve('iauth_1CmMk2IyNTgGDVfzFKlCm0gU')
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    authorization = stripe.issuing.Authorization.approve('iauth_1CmMk2IyNTgGDVfzFKlCm0gU')
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    $authorization = \Stripe\Issuing\Authorization::retrieve('iauth_1CmMk2IyNTgGDVfzFKlCm0gU');
    $authorization->approve();
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Authorization authorization = Authorization.retrieve("iauth_1CmMk2IyNTgGDVfzFKlCm0gU");
    authorization.approve();
    
    // Set your secret key: remember to change this 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 charge = stripe.issuing_authorizations.approve('iauth_1CmMk2IyNTgGDVfzFKlCm0gU')
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    authorization, err := Approve("iauth_1CmMk2IyNTgGDVfzFKlCm0gU", &stripe.IssuingAuthorizationParams{})
    
    // Set your secret key: remember to change this 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 AuthorizationService();
    Authorization authorization = service.Approve("iauth_1CmMk2IyNTgGDVfzFKlCm0gU");
    

    This method provides you with complete control over the use of your issued cards, as you can create advanced spending rules based on other information you have. For example, you might want to restrict multi-currency purchases, or prevent physical cards for a subset of users from being used online.

    Verifying your card’s billing information

    Issued cards support AVS (address verification) and CVC checks. These additional measures help prevent your cards from being used fraudulently. For instance, when a card is used to make a purchase online, the business sends the address and card information to us—via the card network—for verification. Stripe then checks if this matches the billing information for the card being used.

    When an authorization request is made, the Authorization object contains the verification_data parameter, with values that describe the outcome of these checks. If no AVS or CVC information is provided, the value of the respective verification_data field is set to not_provided. If the information is correct, the value is match. If incorrect information has been provided, the value is mismatch.

    You can use this information to help determine whether authorizations should be approved or denied, based on the level of risk you’re willing to accept.

    Updates to authorizations

    Businesses of certain categories have the ability to request additional funds from an existing authorization. For instance, a hotel needing to extend the length of a reservation can increase the amount of the original authorization, instead of charging the card to create another authorization request.

    Should this occur, we send another issuing_authorization.request event for the same Authorization object for you to approve the updated amount. This contains values for pending_authorized_amount and pending_held_amount that represent the additional amount requested.

    For example, an authorization request that was originally approved for $100 might be updated for an additional $200. This subsequent request uses the same Authorization object as before. If the subsequent request is approved, the total amount authorized increases to $300.

    Stage Pending Authorized Amount Authorized Amount
    Original authorization request $100 0
    After original request was approved 0 $100
    Updated authorization request $200 $100
    After updated request was approved 0 $300

    This process only occurs if a business requests more funds for a purchase. If a business reduces the amount of funds requested for an authorization, we automatically reduce the authorized_amount on the original authorization and send the issuing_authorization.updated event to notify you.

    Purchases in different currencies

    Issued cards can be used for purchases in any currency that is supported by the card network. Stripe automatically converts this into the card’s currency when holding or deducting funds, based on the card network’s daily rate. The values for authorized_amount and authorized_currency on the Authorization object are provided in the amount of the currency used.

    The held_amount represents the expected amount the authorization will settle for. The conversion rate and amount held is not final until the authorization has been captured. The final amount and currency is provided as value for amount and currency on the transaction that is subsequently created.

    Next steps

    Read on to learn more about transactions or disputes.

    On this page