> For the complete documentation index, see [llms.txt](https://docs.vibrant.io/vibrant/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.vibrant.io/vibrant/vibrant-sandbox/payment-flow.md).

# Payment flow

## Payments

System overview of a succesful payment.

<figure><img src="/files/0gjeMTyfAcbxuC3MjtNR" alt=""><figcaption><p>Create a payment</p></figcaption></figure>

### **Step 1**

To initiate a payment, create a payment intent from your POS system towards the process\_payment\_intent endpoint of the Vibrant API. In return you get a unique id of the payment intent object created in the system.

A terminal Id must be supplied in the request in order to select a terminal device.

A payment intent cannot be updated. To change the amount a new payment intent should be created.

{% hint style="success" %}
*Idempotency*

[It is possible to provide a unique idempotency key with your request to avoid creating the same request multiple times](#user-content-fn-1)[^1][ by mistake.](#user-content-fn-1)[^1]
{% endhint %}

### **Step 2**

The customer tabs their card against the terminal to initiate the transaction.

The payment intent will change status to succeeded, when/if the transaction is approved.

{% hint style="info" %}
During this step the terminal object will indicate that the terminal is busy, and it is not possible to send other payments/refunds to this terminal at this point.

It is however possible to send a cancel action to the terminal to abort the payment being processed. See more details under [Terminal actions](/vibrant/vibrant-sandbox/terminal-actions.md).
{% endhint %}

### **Step 3**

Update your POS system with status of the payment intent. Either subscribe to a webhook to get events pushed, or pull the data using the id of the payment intent.

## Payment Intent states

Here is an overview of the state changes that a payment intent can overcome.

<figure><img src="/files/CMwwUxs7jCJaRpwahh2Q" alt=""><figcaption></figcaption></figure>

`requires_payment_method`

This state is used when the payment intent is initially created.&#x20;

If the payment fails during `processing` the state can return to `requires_payment_method`. For instance if the credit card is declined. The payment intent can be sent for processing on a terminal again.

`requires_action`

The payment intent will be in this state if the payment awaits the customer to enter PIN code.

`processing`

This state is used when the payment is being processed. It can no longer be cancelled.

{% hint style="info" %}
At this point a Charge object is also created. The charge will hold card details, failure message, receipt id, refund information and more.

More charges can be created for the same payment intent, if that payment fails and is tried again.
{% endhint %}

`succeeded`

The payment has succeeded.

`cancelled`

The payment has been cancelled. Please create a new Payment Intent to start another payment.

## Refunds

The flow for refunds is exactly the same as for payment intents.

To process a refund, you must provide the id of a successful Payment Intent. It is only possible to refund the entire amount - no partial refunds.

A payment intent can only be refunded once.

[^1]:
