# Subscriptions

<details>

<summary>Server2Server</summary>

{% hint style="success" %}
The endpoints described in this solution are restricted for usage of PCI compliant merchants that can securely handle credit card information.
{% endhint %}

#### Subscription creation

The Server2Server solution can handle subscriptions, the integration should scope the endpoint **`v3/subscriptions`**  and sending the subscription details within the **`subscription[]`** object such as:

* **`start_date`** for when the charges should start (e.g.: 2025-07-23)
  * Note that when the `start_date` is within the same day that the subscription is being created, the first charge will be created immediately.
* **`plan`** indicating the frequency with which the charges shoud occur (e.g.: **`MONTHLY`**)
* **`plan_unit`**" indicating how many times the **`plan`** should be charged (e.g: **`3`**)
* **`auto_renewal`** indicating if the subscription should autorenew when it finishes.

<pre class="language-sh"><code class="lang-sh">curl -L \
  --request POST \
<strong>  --url 'https://cc-api-stg.pandablue.com/v3/subscriptions' \
</strong>  --header 'Content-Type: application/json' \
  --header 'X-Date: 2025-07-23T13:15:37.549Z' \
  --header 'X-Login: text' \
  --header 'Authorization: text' \
  --data '{
    "invoice_id": "INV123456",
    "amount": 70,
    "currency": "BRL",
    "country": "BR",
    "payer": {
      "id": "PAYER123",
      "document": 123456789,
      "document_type": "CPF",
      "email": "robertocarlos@example.com",
      "first_name": "Roberto",
      "last_name": "Carlos"
    },
    "description": "Premium Subscription",
<strong>    "subscription": {
</strong><strong>      "start_date": "2025-07-23",
</strong><strong>      "plan": "MONTHLY",
</strong><strong>      "plan_unit": 3,
</strong><strong>      "auto_renewal": false
</strong><strong>    },
</strong><strong>    "credit_card": {
</strong><strong>      "cvv": "123",
</strong><strong>      "card_number": "4111111111111111",
</strong><strong>      "expiration_month": "12",
</strong><strong>      "expiration_year": "25",
</strong><strong>      "holder_name": "John Doe"
</strong><strong>    },
</strong>    "client_ip": "192.168.1.1",
    "back_url": "https://example.com/back",
    "success_url": "https://example.com/success",
    "error_url": "https://example.com/error",
    "notification_url": "https://example.com/notify"
  }'
</code></pre>

You will receive the identifier of the created subscription (**`subscription_id`**) as a response.

{% code title="Response of the Server2Server subscription endpoint" %}

```json
{
  "subscription_id": 358
}
```

{% endcode %}

We will take care of doing all the subsequent charges based on the **`subscription[]`** information provided.

You will receive webhook notifications each time that a deposit was charged in concept of a subscription, in order for you to retrieve the status and matching it to the **`subscription_id` :**&#x20;

{% code title="Example webhook notification" %}

```json
{
    "deposit_id": 3000000001
}
```

{% endcode %}

> For more information regarding webhooks, visit the [API Reference](https://docs.pandablue.com/guides/deposits/create-deposits/notifications).

#### Retrieve the deposit status

When you retrieve the status of a deposit, you will know to which **`subscription_id`** correspond.

<pre class="language-json" data-title="Example response deposit status retrieve with subscription_id"><code class="lang-json">{
  "user_id": "11",
  "deposit_id": 3000000001,
<strong>  "subscription_id":358,
</strong>  "invoice_id": "989409592",
  "country": "BR",
  "currency": "BRL",
  "local_amount": 70,
  "usd_amount": 12.60,
  "bonus_amount": 00.00,
  "bonus_relative": false,
  "payment_method": "VI",
  "payment_type": "CREDIT_CARD",
<strong>  "status": "COMPLETED",
</strong>  "payer": {
    "id": "PAYER123",
    "document": 123456789,
    "document_type": "CPF",
    "email": "robertocarlos@example.com",
    "first_name": "Roberto",
    "last_name": "Carlos"
  },
  "fee_amount": 2.5,
  "fee_currency": "USD",
  "refunded": false,
  "current_payer_verification": "UNMATCHED",
  "card_detail": {
    "card_holder": "Roberto Carlos",
    "brand": "Visa",
    "masked_card": "4111 11** **** 1111",
    "expiration": "2025-12",
    "card_type": "CREDIT",
    "transaction_result": "Transaction Approved"
  }
}
</code></pre>

> For more information regarding deposit status retrieval, visit the [API Reference](https://app.gitbook.com/s/VNE8t2FopKfzgQzTjlBb/deposits-api/manage-payments/get-deposit-status).

#### Retrieve the Subscription details

You can then retrieve the status of the subscription with the **`subscription_id`** for further details.

```json
{
  "id": 219,
  "status": "PENDING",
  "start_date": "2025-07-23",
  "end_date": "2025-10-23",
  "last_renovation_date": null,
  "creation_date": "2025-07-23T13:15:37.54",
  "subscription_plan": "MONTHLY",
  "plan_unit": 3,
  "amount": 70,
  "auto_renewal": false,
  "last_modified_date": "2025-07-23T13:15:37.54",
  "renewals": 0,
  "cancellation_date": null,
  "currency": "BRL",
  "last_charge_date": "2020-10-03",
  "payment_method": "VI",
  "invoice_id": "INV123456",
  "error_url": "https://example.com/error",
  "success_url": "https://example.com/success",
  "back_url": "https://example.com/back",
  "description": "Premium Subscription",
  "country": "BR",
  "deposits": [
    {
      "deposit_id": "3000000001",
      "status": "COMPLETED"
    }
  ]
}
```

> For more information regarding the Subscription details endpoint, visit the [API Reference](https://app.gitbook.com/s/VNE8t2FopKfzgQzTjlBb/deposits-api/manage-subscriptions/get-a-subscription).

#### Reattempts logic

Note that if by any means, a deposit within a subscription fails, in the spirit of maximizing the success scenario we will reattempt the transaction **twice**.\
One attempt each subsequent day will be performed.

</details>

<details>

<summary>Server2Server with an external billing engine</summary>

{% hint style="success" %}
The endpoints described in this solution are restricted for usage of PCI compliant merchants that can securely handle credit card information.
{% endhint %}

#### Tokenize the customer's card

Our card-on-file API lets you securely store customer payment information and charge recurring payments without handling sensitive card data after the initial tokenization.

1. Collect the customer's card information securely via your PCI-compliant form
2. Call our [card-on-file API](https://app.gitbook.com/s/VNE8t2FopKfzgQzTjlBb/deposits-api/saving-cards-card-on-file) to store the card
3. Receive a **`card_identifier`** token that represents the stored card

<pre class="language-json" data-title="Example response of card-on-file API"><code class="lang-json">{
  "holder_name": "Luis Perez",
  "expiration_month": 10,
  "expiration_year": 2028,
  "last_four_digits": "1111",
<strong>  "card_identifier": "CID-2210908e-6d8e-468d-9eb3-d551e8b541a0"
</strong>}
</code></pre>

#### Create a subscription

1. Associate the **`card_identifier`** with your internal subscription record
2. Generate a unique **`external_subscription_id`** in your system
3. Store both identifiers for future transactions

#### Process recurring charges

When it's time to charge the customer:

1. Call our Server2Server deposit endpoint
2. Instead of sending full card details, send:
   * The **`card_identifier`** token
   * Your **`external_subscription_id`**

<pre class="language-sh" data-title="Example request Server2Server with an external billing engine" data-overflow="wrap"><code class="lang-sh">curl -L \
  --request POST \
<strong>  --url 'https://cc-api-stg.pandablue.com/v3/deposits' \
</strong>  --header 'Content-Type: application/json' \
  --header 'X-Date: 2025-07-15T12:57:14.936Z' \
  --header 'X-Login: text' \
  --header 'Authorization: text' \
  --data '{
    "invoice_id": "800000001",
    "amount": 1000,
    "country": "BR",
    "currency": "BRL",
    "payer": {
      "id": "11111",
      "document": "84932568207",
      "document_type": "CPF",
      "email": "johnSmith12@hotmail.com",
      "first_name": "John",
      "last_name": "Smith"
    },
<strong>    "card_identifier": "CID-2210908e-6d8e-468d-9eb3-d551e8b541a0",
</strong><strong>     "external_subscription_id": "ABC1234",
</strong>    "client_ip": "123.123.123.123"
  }'
</code></pre>

{% hint style="info" %}

#### Subscription endpoints

Note that as this solution handles all the subscription on the merchant's end, no subscription entity is created on our end. Therefore the subscription endpoints should be used.
{% endhint %}

</details>

<details>

<summary>OneShot with card-on-file</summary>

#### Subscription creation

The OneShot solution can create subscriptions in cards that were previously stored on file.

{% hint style="success" %}
Note that this subscription flow has a pre-requisite to have a card stored on file.\
Please visit [Card-on-file](https://docs.pandablue.com/guides/deposits/create-deposits/credit-cards/card-on-file) section to explore the ways in which this can be done.
{% endhint %}

The integration should scope the endpoint **`v3/subscriptions`** , while sending the **`card_identifier`** and the subscription details within the **`subscription[]`** object such as:

* **`start_date`** for when the charges should start (e.g.: 2025-07-23)
  * Note that when the `start_date` is within the same day that the subscription is being created, the first charge will be created immediately.
* **`plan`** indicating the frequency with which the charges shoud occur (e.g.: **`MONTHLY`**)
* **`plan_unit`**" indicating how many times the **`plan`** should be charged (e.g: **`3`**)
* **`auto_renewal`** indicating if the subscription should autorenew when it finishes.

<pre class="language-sh"><code class="lang-sh">curl -L \
  --request POST \
<strong>  --url 'https://api-stg.pandablue.com/v3/subscriptions' \
</strong>  --header 'Content-Type: application/json' \
  --header 'X-Date: 2025-07-23T13:15:37.549Z' \
  --header 'X-Login: text' \
  --header 'Authorization: text' \
  --data '{
    "invoice_id": "INV123456",
    "amount": 70,
    "currency": "BRL",
    "country": "BR",
    "payer": {
      "id": "PAYER123",
      "document": 123456789,
      "document_type": "CPF",
      "email": "robertocarlos@example.com",
      "first_name": "Roberto",
      "last_name": "Carlos"
    },
    "description": "Premium Subscription",
<strong>    "subscription": {
</strong><strong>      "start_date": "2025-07-23",
</strong><strong>      "plan": "MONTHLY",
</strong><strong>      "plan_unit": 3,
</strong><strong>      "auto_renewal": false
</strong><strong>    },
</strong><strong>    
</strong><strong>,
</strong>    "client_ip": "192.168.1.1",
    "back_url": "https://example.com/back",
    "success_url": "https://example.com/success",
    "error_url": "https://example.com/error",
    "notification_url": "https://example.com/notify"
  }'
</code></pre>

You will receive the identifier of the created subscription (**`subscription_id`**) as a response.

{% code title="Response of the Server2Server subscription endpoint" %}

```json
{
  "subscription_id": 358
}
```

{% endcode %}

We will take care of doing all the subsequent charges based on the **`subscription[]`** information provided.

You will receive webhook notifications each time that a deposit was charged in concept of a subscription, in order for you to retrieve the status and matching it to the **`subscription_id` :**&#x20;

{% code title="Example webhook notification" %}

```json
{
    "deposit_id": 3000000001
}
```

{% endcode %}

> For more information regarding webhooks, visit the [API Reference](https://docs.pandablue.com/guides/deposits/create-deposits/notifications).

#### Retrieve the deposit status

When you retrieve the status of a deposit, you will know to which **`subscription_id`** correspond.

<pre class="language-json" data-title="Example response deposit status retrieve with subscription_id"><code class="lang-json">{
  "user_id": "11",
  "deposit_id": 3000000001,
<strong>  "subscription_id":358,
</strong>  "invoice_id": "989409592",
  "country": "BR",
  "currency": "BRL",
  "local_amount": 70,
  "usd_amount": 12.60,
  "bonus_amount": 00.00,
  "bonus_relative": false,
  "payment_method": "VI",
  "payment_type": "CREDIT_CARD",
<strong>  "status": "COMPLETED",
</strong>  "payer": {
    "id": "PAYER123",
    "document": 123456789,
    "document_type": "CPF",
    "email": "robertocarlos@example.com",
    "first_name": "Roberto",
    "last_name": "Carlos"
  },
  "fee_amount": 2.5,
  "fee_currency": "USD",
  "refunded": false,
  "current_payer_verification": "UNMATCHED",
  "card_detail": {
    "card_holder": "Roberto Carlos",
    "brand": "Visa",
    "masked_card": "4111 11** **** 1111",
    "expiration": "2025-12",
    "card_type": "CREDIT",
    "transaction_result": "Transaction Approved"
  }
}
</code></pre>

> For more information regarding deposit status retrieval, visit the [API Reference](https://app.gitbook.com/s/VNE8t2FopKfzgQzTjlBb/deposits-api/manage-payments/get-deposit-status).

#### Retrieve the Subscription details

You can then retrieve the status of the subscription with the **`subscription_id`** for further details.

<pre class="language-json"><code class="lang-json">{
  "id": 219,
  "status": "PENDING",
  "start_date": "2025-07-23",
  "end_date": "2025-10-23",
  "last_renovation_date": null,
  "creation_date": "2025-07-23T13:15:37.54",
  "subscription_plan": "MONTHLY",
  "plan_unit": 3,
  "amount": 70,
  "auto_renewal": false,
  "last_modified_date": "2025-07-23T13:15:37.54",
  "renewals": 0,
  "cancellation_date": null,
  "currency": "BRL",
  "last_charge_date": "2020-10-03",
  "payment_method": "VI",
  "invoice_id": "INV123456",
  "error_url": "https://example.com/error",
  "success_url": "https://example.com/success",
  "back_url": "https://example.com/back",
  "description": "Premium Subscription",
  "country": "BR",
<strong>  "deposits": [
</strong><strong>    {
</strong><strong>      "deposit_id": "3000000001",
</strong><strong>      "status": "COMPLETED"
</strong><strong>    }
</strong><strong>  ]
</strong>}
</code></pre>

> For more information regarding the Subscription details endpoint, visit the [API Reference](https://app.gitbook.com/s/VNE8t2FopKfzgQzTjlBb/deposits-api/manage-subscriptions/get-a-subscription).

#### Reattempts logic

Note that if by any means, a deposit within a subscription fails, in the spirit of maximizing the success scenario we will reattempt the transaction **twice**.\
One attempt each subsequent day will be performed.

</details>

<details>

<summary>OneShot with redirect</summary>

#### Subscription creation

The OneShot solution can handle subscriptions, the integration should scope the endpoint **`v3/subscriptions`**  and sending the subscription details within the **`subscription[]`** object such as:

* **`start_date`** for when the charges should start (e.g.: 2025-07-23)
  * Note that when the `start_date` is within the same day that the subscription is being created, the first charge will be created immediately.
* **`plan`** indicating the frequency with which the charges shoud occur (e.g.: **`MONTHLY`**)
* **`plan_unit`**" indicating how many times the **`plan`** should be charged (e.g: **`3`**)
* **`auto_renewal`** indicating if the subscription should auto-renew when it finishes.

<pre class="language-sh" data-title="Example request OneShot for Subscriptions"><code class="lang-sh">curl -L \
  --request POST \
<strong>  --url 'https://api-stg.pandablue.com/v3/subscriptions' \
</strong>  --header 'Content-Type: application/json' \
  --header 'X-Date: 2025-07-24T13:44:21.195Z' \
  --header 'X-Login: text' \
  --header 'Authorization: text' \
  --data '{
    "invoice_id": "INV123456",
    "amount": 50,
    "currency": "BRL",
    "country": "BR",
    "payer": {
      "id": "PAYER123",
      "document": 123456789,
      "document_type": "CPF",
      "email": "robertocarlos@example.com",
      "first_name": "Roberto",
      "last_name": "Carlos"
    },
    "description": "Premium Subscription",
<strong>    "subscription": {
</strong><strong>      "start_date": "2025-01-01",
</strong><strong>      "plan": "MONTHLY",
</strong><strong>      "plan_unit": 1,
</strong><strong>      "auto_renewal": false
</strong><strong>    },
</strong>    "client_ip": "192.168.1.1",
    "back_url": "https://example.com/back",
    "success_url": "https://example.com/success",
    "error_url": "https://example.com/error",
    "notification_url": "https://example.com/notify"
  }'
</code></pre>

We will take care of doing all the subsequent charges based on the **`subscription[]`** information provided.

In the response you will receive:

* the **`subscription_id`** &#x20;
* the **`redirect_url`** containing the credit card form for the user to input their card details.

<pre class="language-json" data-title="Example response subscriptions OneShot "><code class="lang-json">{
<strong>  "subscription_id": 358,
</strong><strong>  "redirect_url": "https://checkout.cc-stg.checkoutogate.net/validate/6mIsesbbmvYn2hzAOwuYQSMAYIyISUgl?subscriptionId=513",
</strong>  "expiration_date": "2025-03-06 15:58:02",
  "payment_amount": 50,
  "redirect": true
}
</code></pre>

<figure><img src="https://content.gitbook.com/content/f92vedEnowdVWbjM4Cmd/blobs/RXIVknezIEu9g6O8HBrD/Subscriptions%20Checkout.png" alt="" width="166"><figcaption></figcaption></figure>

{% hint style="success" %}
Note that we will perform micro deposit charges to the card prior accepting it as. payment method for the subscription billing.
{% endhint %}

&#x20;Webhook notifications will be sent each time that changes occured within a deposit, such as status changes to completed, in order for you to retrieve the status and matching it to the **`subscription_id` :**&#x20;

{% code title="Example webhook notification" %}

```json
{
    "deposit_id": 3000000001
}
```

{% endcode %}

> For more information regarding webhooks, visit the [API Reference](https://docs.pandablue.com/guides/deposits/create-deposits/credit-cards/broken-reference).

#### Retrieve the deposit status

When you retrieve the status of a deposit, you will know to which **`subscription_id`** correspond.

<pre class="language-json" data-title="Example response deposit status retrieve with subscription_id"><code class="lang-json">{
  "user_id": "11",
<strong>  "deposit_id": 3000000001,
</strong><strong>  "subscription_id":358,
</strong>  "invoice_id": "989409592",
  "country": "BR",
  "currency": "BRL",
  "local_amount": 50,
  "usd_amount": 12.60,
  "bonus_amount": 00.00,
  "bonus_relative": false,
  "payment_method": "VI",
  "payment_type": "CREDIT_CARD",
<strong>  "status": "COMPLETED",
</strong>  "payer": {
    "id": "PAYER123",
    "document": 123456789,
    "document_type": "CPF",
    "email": "robertocarlos@example.com",
    "first_name": "Roberto",
    "last_name": "Carlos"
  },
  "fee_amount": 2.5,
  "fee_currency": "USD",
  "refunded": false,
  "current_payer_verification": "UNMATCHED",
  "card_detail": {
    "card_holder": "Roberto Carlos",
    "brand": "Visa",
    "masked_card": "4111 11** **** 1111",
    "expiration": "2025-12",
    "card_type": "CREDIT",
    "transaction_result": "Transaction Approved"
  }
}
</code></pre>

> For more information regarding deposit status retrieval, visit the [API Reference](https://app.gitbook.com/s/VNE8t2FopKfzgQzTjlBb/deposits-api/manage-payments/get-deposit-status).

#### Retrieve the Subscription details

You can then retrieve the status of the subscription with the **`subscription_id`** for further details.

```json
{
  "id": 219,
  "status": "PENDING",
  "start_date": "2025-07-23",
  "end_date": "2025-10-23",
  "last_renovation_date": null,
  "creation_date": "2025-07-23T13:15:37.54",
  "subscription_plan": "MONTHLY",
  "plan_unit": 3,
  "amount": 70,
  "auto_renewal": false,
  "last_modified_date": "2025-07-23T13:15:37.54",
  "renewals": 0,
  "cancellation_date": null,
  "currency": "BRL",
  "last_charge_date": "2020-10-03",
  "payment_method": "VI",
  "invoice_id": "INV123456",
  "error_url": "https://example.com/error",
  "success_url": "https://example.com/success",
  "back_url": "https://example.com/back",
  "description": "Premium Subscription",
  "country": "BR",
  "deposits": [
    {
      "deposit_id": "3000000001",
      "status": "COMPLETED"
    }
  ]
}
```

> For more information regarding the Subscription details endpoint, visit the [API Reference](https://app.gitbook.com/s/VNE8t2FopKfzgQzTjlBb/deposits-api/manage-subscriptions/get-a-subscription).

#### Reattempts logic

Note that if by any means, a deposit within a subscription fails, in the spirit of maximizing the success scenario we will reattempt the transaction **twice**.\
One attempt each subsequent day will be performed.

</details>
