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

# Stripe - SPEI

> Configure SPEI via Stripe as a bank transfer payment method in Gr4vy.

SPEI is a Mexican bank transfer scheme that provides real-time bank transfers using a reference number.

## Supported countries and currencies

Stripe supports transactions from buyers in `MX`.

Stripe supports processing payments in `MXN`.

Follow the [Stripe setup instructions](./stripe) before configuring SPEI.

## Configuration

For shared APM credentials, see [Stripe APM credentials](./stripe#apm-credentials).

### Approval URL (optional)

By default, the connector returns an approval URL that redirects buyers to a Stripe-hosted page with instructions for completing a bank transfer. If required, you can set a different approval URL here which allows you to build your own page for showing bank transfer instructions to buyers. When set, the Approval URL is returned with a Session Token appended as a query parameter named `token`. This Session Token can be used with the [Transaction Session API](https://docs.gr4vy.com/reference/transactions/get-transaction-session) to retrieve the [details](https://docs.stripe.com/api/payment_intents/object#payment_intent_object-next_action-display_bank_transfer_instructions) required to build your own page.

## Webhooks

SPEI payments and refunds are completed asynchronously, so webhooks must be configured to update the status of transactions. Webhooks are configured in the Stripe Dashboard within Developer Settings under **Webhooks**.

The SPEI connector relies on the following Stripe webhooks:

* `payment_intent.succeeded`
* `payment_intent.partially_funded`
* `payment_intent.canceled`
* `charge.refund.updated`

## Integration

The default integration for SPEI via Stripe uses a redirect to a payments page hosted by Stripe.

### Redirect integration

Start by creating a new transaction with the following required fields.

<CodeGroup>
  ```csharp C# theme={"system"}
  var transaction = await client.Transactions.CreateAsync(
      transactionCreate: new TransactionCreate()
      {
          Amount = 1299,
          Currency = "MXN",
          Country = "MX",
          PaymentMethod =
              TransactionCreatePaymentMethod.CreateRedirectPaymentMethodCreate(
                  new RedirectPaymentMethodCreate()
                  {
                      Method = "spei",
                      Country = "MX",
                      Currency = "MXN",
                      RedirectUrl = "https://example.com/callback",
                  }
              ),
      }
  );
  ```

  ```go Go theme={"system"}
  amount := int64(1299)
  currency := "MXN"
  country := "MX"
  method := components.RedirectPaymentMethodCreateMethodSpei
  redirectUrl := "https://example.com/callback"

  redirectPaymentMethodCreate := components.RedirectPaymentMethodCreate{
      Method: method,
      Country: country,
      Currency: currency,
      RedirectURL: redirectUrl,
  }
  paymentMethod := components.CreateTransactionCreatePaymentMethodRedirectPaymentMethodCreate(redirectPaymentMethodCreate)

  transactionCreate := components.TransactionCreate{
      Amount:        amount,
      Currency:      currency,
      Country:       &country,
      PaymentMethod: &paymentMethod,
  }

  transaction, err := client.Transactions.Create(ctx, transactionCreate, nil, nil, nil)
  ```

  ```java Java theme={"system"}
  CreateTransactionResponse transactionResponse = gr4vyClient.transactions().create()
      .transactionCreate(TransactionCreate.builder()
          .amount(1299L)
          .currency("MXN")
          .country("MX")
          .paymentMethod(TransactionCreatePaymentMethod.of(RedirectPaymentMethodCreate.builder()
              .method(RedirectPaymentMethodCreateMethod.SPEI)
              .country("MX")
              .currency("MXN")
              .redirectUrl("https://example.com/callback")
              .build()))
          .build())
      .call();

  Transaction transaction = transactionResponse.transaction().orElse(null);
  ```

  ```php PHP theme={"system"}
  $transactionCreate = new TransactionCreate(
      amount: 1299,
      currency: 'MXN',
      country: 'MX',
      paymentMethod: new RedirectPaymentMethodCreate(
          method: 'spei',
          country: 'MX',
          currency: 'MXN',
          redirectUrl: 'https://example.com/callback'
      )
  );
  $response = self::$sdk->transactions->create($transactionCreate);
  $transaction = $response->transaction;
  ```

  ```python Python theme={"system"}
  transaction: models.Transaction = client.transactions.create(
      amount=1299,
      currency="MXN",
      country="MX",
      payment_method={
          "method": "spei",
          "country": "MX",
          "currency": "MXN",
          "redirect_url": "https://example.com/callback",
      }
  )
  ```

  ```ts TypeScript theme={"system"}
  const transaction = await gr4vy.transactions.create({
      amount: 1299,
      currency: "MXN",
      country: "MX",
      paymentMethod: {
          method: "spei",
          country: "MX",
          currency: "MXN",
          redirectUrl: "https://example.com/callback"
      }
  })
  ```
</CodeGroup>

After the transaction is created, the API response includes a
`payment_method.approval_url` and the status is set to `processing`.

```json theme={"system"}
{
  "type": "transaction",
  "id": "ea1efdd0-20f9-44d9-9b0b-0a3d71e9b625",
  "payment_method": {
    "type": "payment-method",
    "approval_url": "https://payments.stripe.com/bank_transfers/instructions/test..."
  },
  "method": "spei"
}
```

Redirect the buyer to the `approval_url` (open in a browser or Webview), where they see instructions for completing a bank transfer.

Once the buyer completes a bank transfer, the transaction progresses to a `capture_succeeded` state in response to a webhook from Stripe.

### Direct integration

If you intend to use your own hosted page for presenting the buyer with bank transfer instructions, you can include an `integration_client` parameter set to `web`, `ios` or `android` when creating a new transaction.

<CodeGroup>
  ```csharp C# theme={"system"}
  var transaction = await client.Transactions.CreateAsync(
      transactionCreate: new TransactionCreate()
      {
          Amount = 1299,
          Currency = "MXN",
          Country = "MX",
          IntegrationClient = "ios",
          PaymentMethod =
              TransactionCreatePaymentMethod.CreateRedirectPaymentMethodCreate(
                  new RedirectPaymentMethodCreate()
                  {
                      Method = "spei",
                      Country = "MX",
                      Currency = "MXN",
                      RedirectUrl = "myapp://callback",
                  }
              ),
      }
  );
  ```

  ```go Go theme={"system"}
  amount := int64(1299)
  currency := "MXN"
  country := "MX"
  integrationClient := "ios"
  method := components.RedirectPaymentMethodCreateMethodSpei
  redirectUrl := "myapp://callback"

  redirectPaymentMethodCreate := components.RedirectPaymentMethodCreate{
      Method: method,
      Country: country,
      Currency: currency,
      RedirectURL: redirectUrl,
  }
  paymentMethod := components.CreateTransactionCreatePaymentMethodRedirectPaymentMethodCreate(redirectPaymentMethodCreate)

  transactionCreate := components.TransactionCreate{
      Amount:            amount,
      Currency:          currency,
      Country:           &country,
      IntegrationClient: &integrationClient,
      PaymentMethod:     &paymentMethod,
  }

  transaction, err := client.Transactions.Create(ctx, transactionCreate, nil, nil, nil)
  ```

  ```java Java theme={"system"}
  CreateTransactionResponse transactionResponse = gr4vyClient.transactions().create()
      .transactionCreate(TransactionCreate.builder()
          .amount(1299L)
          .currency("MXN")
          .country("MX")
          .integrationClient("ios")
          .paymentMethod(TransactionCreatePaymentMethod.of(RedirectPaymentMethodCreate.builder()
              .method(RedirectPaymentMethodCreateMethod.SPEI)
              .country("MX")
              .currency("MXN")
              .redirectUrl("myapp://callback")
              .build()))
          .build())
      .call();

  Transaction transaction = transactionResponse.transaction().orElse(null);
  ```

  ```php PHP theme={"system"}
  $transactionCreate = new TransactionCreate(
      amount: 1299,
      currency: 'MXN',
      country: 'MX',
      integrationClient: 'ios',
      paymentMethod: new RedirectPaymentMethodCreate(
          method: 'spei',
          country: 'MX',
          currency: 'MXN',
          redirectUrl: 'myapp://callback'
      )
  );
  $response = self::$sdk->transactions->create($transactionCreate);
  $transaction = $response->transaction;
  ```

  ```python Python theme={"system"}
  transaction: models.Transaction = client.transactions.create(
      amount=1299,
      currency="MXN",
      country="MX",
      integration_client="ios",
      payment_method={
          "method": "spei",
          "country": "MX",
          "currency": "MXN",
          "redirect_url": "myapp://callback",
      }
  )
  ```

  ```ts TypeScript theme={"system"}
  const transaction = await gr4vy.transactions.create({
      amount: 1299,
      currency: "MXN",
      country: "MX",
      integrationClient: "ios",
      paymentMethod: {
          method: "spei",
          country: "MX",
          currency: "MXN",
          redirectUrl: "myapp://callback"
      }
  })
  ```
</CodeGroup>

After the transaction is created, the API response includes a `session_token`. You use this token with the [session endpoint](/reference/transactions/get-transaction-session) to retrieve the session data for the transaction and build a custom page that displays the bank transfer instructions.

```json theme={"system"}
POST /transactions/:transaction_id/session?token=:session_token

{
    "session_data": {
        "paymentIntentId": "pi_3StlgnRAbJldLcy50NYwrdAN",
        "bankTransferInstructions": {
            "type": "mx_bank_transfer",
            "currency": "mxn",
            "reference": "266688",
            "amount_remaining": 1000,
            "financial_addresses": [
                {
                    "spei": {
                        "clabe": "124180613177193525",
                        "bank_code": "124",
                        "bank_name": "CITI MEXICO",
                        "bank_address": {
                            "city": "Naucalpan",
                            "line1": "Blvd. Manuel Avila Camacho 1902",
                            "line2": "Planta Baja, Cd. Satelite",
                            "state": "Estado de Mexico",
                            "country": "MX",
                            "postal_code": "C.P. 53100"
                        },
                        "account_holder_name": "Gr4vy sandbox",
                        "account_holder_address": {
                            "city": "Ciudad de México",
                            "line1": "Av Paseo de la Reforma 180 piso 29 col Juarez",
                            "line2": null,
                            "state": "Ciudad de México",
                            "country": "MX",
                            "postal_code": "06600"
                        }
                    },
                    "type": "spei",
                    "supported_networks": [
                        "spei"
                    ]
                }
            ],
            "hosted_instructions_url": "https://payments.stripe.com/bank_transfers/instructions/test_YWNjdF8xU29peEtSQWJKbGRMY3k1LF9UcnRKS1JrUExGMHVUTmR6bjVJQWxOWGd3SXpoNks20100O3vRPYrH"
        }
    },
    "default_completion_url": "https://example.com/callback",
    "integration_client": "ios"
}
```
