> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getlago.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Payment pre-authorization

> Learn how to validate payment methods before creating, upgrading, or downgrading customer subscriptions.

<Warning>
  **Stripe Integration Only**

  While Lago supports multiple payment providers, payment pre-authorization is currently only available with Stripe.
</Warning>

## Introduction

By default, when creating a subscription, Lago follows this process:

1. Creates and activates the subscription (unless scheduled for the future or it's a downgrade);
2. Generates the invoice asynchronously; and
3. Processes the payment asynchronously.

This means it's possible to create an active subscription for a customer even if the payment later fails. While this behavior is intentional, it may not be ideal for all use cases.

To address this, Lago now offers payment pre-authorization, **allowing you to verify the validity of a payment method for a specific amount before creating the subscription.**

<Info>
  **Important**: If the pre-authorization fails, the entire process is aborted and no subscription is created.
</Info>

## How Pre-Authorization Works

Pre-authorization creates a Payment Intent in Stripe to verify that the payment amount can be collected. When successful, the amount is temporarily held on the customer's account but not captured.

**Note**: The held funds are automatically released immediately after successful verification.

### Supported payment methods

Pre-authorization relies on Stripe's manual capture, so it only works with payment methods that support it. Cards and Link do; methods such as SEPA Direct Debit or Boleto do not, and using one returns a `provider_error` without creating the subscription.

The exact list depends on the payment methods enabled on your Stripe account. Refer to the **Manual capture** column of [Stripe's payment method support matrix](https://docs.stripe.com/payments/payment-methods/payment-method-support).

Pre-authorization can fail if the card details are invalid, if the customer has insufficient funds, or if the payment method type does not support manual capture.

Please note that if 3DS is required during pre-authorization, the card is considered valid and the subscription is created.

## Understanding the limitations

While pre-authorization helps reduce payment failures, it cannot guarantee successful invoice payment because:

1. Conditions may change between pre-authorization and actual payment:
   * Customer's account balance may decrease
   * Card may be blocked or expired
2. A bank might approve the pre-authorization but still require 3D Secure authentication for the actual payment

## Implementation guide

To implement pre-authorization, use the `POST /api/v1/subscriptions` endpoint with additional parameters. The standard `subscription` parameters remain unchanged.

You must manually specify the amount to authorize, as the final amount (including taxes) is only calculated during invoice generation.

### Request format

```json theme={"dark"}
{
  "authorization": {
    "amount_cents": 100,    // Amount in cents (e.g., 100 = 1 EUR)
    "amount_currency": "EUR"
  },
  "subscription": {
    // Standard subscription parameters
  }
}
```

### Success response

The response contains an `authorization` object describing the Stripe Payment Intent, alongside the created subscription.

```json theme={"dark"}
{
  "authorization": {
    "id": "pi_1a901a901a901a901a901a90",
    "object": "payment_intent",
    "amount": 5000,
    "amount_capturable": 5000,
    "status": "requires_capture"
  },
  "subscription": {
    // Standard subscription object
  }
}
```

A `requires_capture` status means the amount is held and about to be released. When 3D Secure is required, the status is `requires_action` and the subscription is still created.

### Error response

```json theme={"dark"}
{
  "status": 422,
  "error": "Unprocessable Entity",
  "code": "provider_error",
  "provider": {
    "code": "stripe_code"
  },
  "error_details": {
    "code": "error_code",
    "message": "error_message",
    "request_id": "request_id",
    "http_status": "http_status",
    "http_body": {
      // Complete Stripe error response
    }
  }
}
```
