# POS / Terminal Integration

Flute's terminal integration connects your POS application to a Flute terminal for in-person card payments.
Your POS application sends transaction requests to the Flute API, which routes them to the terminal for card interaction (tap, insert, swipe).
The terminal reads the card data and sends it to Flute, which submits the payment to the card processor.

## Integration Overview

1. Your POS application creates a transaction through the API, specifying the terminal and amount.
2. Flute sends the transaction to the terminal.
3. The terminal prompts the customer to present their card.
4. The terminal reads the card data and sends it to Flute.
5. Flute submits the payment to the card processor and stores the result.
6. Your POS application retrieves the result by polling the API.


```mermaid
sequenceDiagram
    participant POS as POS Application
    participant API as Flute API
    participant Terminal as Flute Terminal

    POS->>API: POST /pos-transactions
    API->>Terminal: Sends transaction to terminal
    Terminal->>Terminal: Customer presents card
    Terminal->>API: Sends card data
    API->>API: Submits to card processor
    POS->>API: GET /pos-transactions/{id} (poll)
    API-->>POS: Transaction result
```

## Building with Flute Terminals

All API requests use the following base URLs.
Use the sandbox environment during development and testing, and switch to production when you are ready to go live.

**Sandbox Environment:**

```
https://sandbox.api.flute.com/pos-api/v1
```

**Production Environment:**

```
https://api.flute.com/pos-api/v1
```

## Terminals

Before processing transactions, you need to know which terminals are available.

### List Terminals

To list the available terminals, use: 
`GET /pos-api/v1/terminals`

This returns a paginated list of terminals assigned to your merchant account.

| Parameter | Type | Description |
|  --- | --- | --- |
| page | integerint32 | Indicates the page number. |
| pageSize | integerint32 | Indicates  items per page. |
| search | string | Indicates results from the search by terminal name or serial number. |
| serialNumber | string | Indicates results from the serial number. |


Each terminal in the response includes:

| Field | Description |
|  --- | --- |
| id | Indicates the terminal identifier, also called the `terminalId`. Use this when creating transactions. |
| serialNumber | Indicates the terminal's hardware serial number. |
| terminalManufacturer | Indicates the manufacturer name, such as Sunmi, Verifone. |
| terminalModel | Indicates the model name, such as P2, P3H, Victa Mobile. |
| terminalModeName | Indicates the operating mode, such as `Standalone` or `SemiIntegrated`. |
| connectionStatus | Indicates the current connection state, such as `Online` or `Offline`. |


\

### Get Terminal Status

To display the status of a specified terminal, use: 
`GET /pos-api/v1/terminals/{terminalId}/status`

This returns detailed real-time status for that terminal.

| Field | Description |
|  --- | --- |
| terminalPosStatus | Active (ready to accept transactions) or Busy (currently processing). |
| connectionStatus | Online or Offline. |
| connectionType | WiFi, Mobile, or Ethernet. |
| batteryLevel | Battery percentage (0–100). |
| printerStatus | Normal, NotNormal, or NotSupported. |
| availabilityStatus | Ready or Busy. |


\

Before sending a transaction, check that a terminal is:

* `Online`, from `connectionStatus` and
* `Ready`, from `availabilityStatus`


## Using POS Transactions

The following are individual steps or endpoints used in the POS transaction workflow.

The following topics are available:

* [Starting a POS Transaction](#starting-a-pos-transaction)
* [Payment Method Storage](#payment-method-storage)
* [Retrieving POS Transactions](#retrieving-pos-transactions)
* [Retrieving a Specified POS Transaction](#retrieving-a-specified-pos-transaction)
* [Printing a POS Transaction Receipt](#printing-a-pos-transaction-receipt)
* [Canceling a POS Transaction](#canceling-a-pos-transaction)


### Starting a POS Transaction

To start a new POS transaction, use: 
`POST /pos-api/v1/pos-transactions`

The following are the request parameters.

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| terminalId | stringUUID | Yes | Specifies the terminal that will process the transaction. |
| transactionTypeId | integerint32 | Yes | Specifies the transaction type. See [Transaction Types](#transaction-types). |
| posDeviceId | string | Yes | Specifies your POS application's device identifier. Maximum of 36 characters. |
| currencyId | integerint32 | Yes | Specifies the Flute currency identifier. Always set to **1**. |
| amount | decimal | Conditional | Specifies the transaction amount (in USD).This is required for Sale, Authorization, Capture, Refund, and Tip Adjustment. |
| targetTransactionId | stringUUID | Conditional | Specifies the original transaction identifier.This is required for Void, Capture, and Refund. |
| useCardPrice | boolean | Conditional | Specifies the price type in the amount field.This is required when the merchant's zero-cost processing option is Dual Pricing.If `true`, the amount is the card price.If `false`, the amount is the cash price.Omit or set to null for other configurations. |
| referenceId | string | No | Specifies your external reference identifier for this transaction. Maximum of 36 characters. |
| customerId | stringUUID | No | Specifies the associated transaction with a stored customer. |
| readingMethodId | integerint32 | No | Specifies the terminal reading mode.If 1, it reads from a card, such as tap, insert, or swipe.If 2, it reads from a manual entry (keyed).The default is 1. |
| waitForAcceptanceByTerminal | boolean | No | Specifies waiting for the terminal.If `true`, the transaction uses long poll until terminal accepts.If `false`, the transaction returns immediatelyThe default is `false`. |
| requestPaymentMethodStorageConsent | boolean | No | Specifies displaying a prompt to save the payment method.If `true`, this displays a prompt on the terminal asking the customer to consent to saving their payment method.If `false`, this does not display a prompt.The default is `false` |
| paymentProcessorId | stringUUID | No | Specifies the payment processor to use for this transaction.If omitted, the merchant's default processor is used. |


**Example — Sale transaction:**

```bash
curl -X POST 'https://sandbox.api.flute.com/pos-api/v1/pos-transactions' \
  -H 'Authorization: Bearer API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "terminalId": "d4e5f6a7-b8c9-0123-4567-89abcdef0123",
    "transactionTypeId": 2,
    "amount": 25.99,
    "posDeviceId": "POS-REGISTER-01",
    "referenceId": "ORDER-4521",
    "waitForAcceptanceByTerminal": false
  }'
```

**Response:**

```json
{
  "posTransactionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "statusId": 1,
  "status": "TerminalConnecting"
}
```

#### Transaction Types

| ID | Type | Description |
|  --- | --- | --- |
| 1 | Authorization | Place a hold on funds without capturing. Requires amount. |
| 2 | Sale | Authorize and capture in one step. Requires amount. |
| 3 | Capture | Capture a previous authorization. Requires amount and targetTransactionId. |
| 4 | Void | Cancel a transaction before settlement. Requires targetTransactionId. |
| 5 | Refund | Return funds from a settled transaction. Requires amount and targetTransactionId. |
| 8 | Tip Adjustment | Adjust the tip on an existing transaction. Requires amount and targetTransactionId. |


### Payment Method Storage

When `requestPaymentMethodStorageConsent` is set to `true`, the terminal displays a consent prompt after the transaction is approved.
This asks the customer if they want to save their payment method for future use (such as one-off payments, future orders, or recurring charges).

A `customerId` must be provided in the request to use this feature.
Without it, the consent prompt will not be shown.
If the card is already saved under the provided customer record, the terminal skips the prompt automatically.

If the customer consents, the payment method is saved to the customer record.
If the customer declines, the transaction is unaffected and no payment method is stored.

To retrieve the stored payment method, call one of the following from the backend after the transaction completes:

* `GET /pay-api/v1/customers/{customerId}`
* `GET /pay-api/v1/customers/{customerId}/payment-methods`


### Retrieving POS Transactions

To retrieve POS transactions, use: 
`GET /pos-api/v1/pos-transactions`

Specified terminals may be listed by filtering with the `terminalId`.

| Parameter | Type | Description |
|  --- | --- | --- |
| page | integerint32 | Page number. |
| pageSize | integerint32 | Items per page. |
| terminalId | stringUUID | Filter transactions by terminal. |
| asc | boolean | Sort order.If `true` the sort is ascending.If `false`, the sort descending. |
| orderBy | string | Field name to sort by. |


This returns a paginated list of POS transactions.

### Retrieving a Specified POS Transaction

To retrieve a specified POS transaction, use: 
`GET /pos-api/v1/pos-transactions/{posTransactionId}`

The following are the input parameters.

| Parameter | Type | Description |
|  --- | --- | --- |
| posTransactionId | stringUUID | Specifies the POS transaction identifier returned from the create call. |
| waitForTransactionProcessing | boolean | Specifies the wait method.If `true`, use long polling. The response holds until the transaction completes or times out.If `false`, use short polling. |


When the transaction completes (`isCompleted: true`), the response includes full transaction details in the `transaction` object:

```json
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "posTransactionStatusId": 6,
  "posTransactionStatus": "Completed",
  "isCompleted": true,
  "amount": 25.99,
  "transaction": {
    "transactionId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "amount": 25.99,
    "transactionStatus": "Captured",
    "authCode": "A12345"
  }
}
```

### Canceling a POS Transaction

You can cancel a transaction that hasn't completed yet.
To cancel a specified POS transaction, use: 
`POST /pos-api/v1/pos-transactions/{posTransactionId}/cancel`

This returns the updated transaction status.
Cancellation is only possible while the transaction is in a non-final state, such as `TerminalConnecting` or `TransactionProcessing`.

## Printing a POS Transaction Receipt

To print a receipt on a terminal for a completed transaction, use: 
`POST /pos-api/v1/pos-transactions/{posTransactionId}/print`

The following is an example request

```json
{
  "posTransactionId": "d4e5f6a7-b8c9-0123-4567-89abcdef0123"
}
```

If successful, this returns a `200 OK` with no response body and will print the receipt

## Polling for Results

After creating a transaction, poll the GET endpoint to track its progress.

### Polling Strategies

**Polling when creating a transaction:**

* **Short polling:** Set `waitForAcceptanceByTerminal: false` when creating the POS transaction.
Your POS controls the polling interval to retrieve the transaction status.
* **Long polling:** Set `waitForAcceptanceByTerminal: true` when creating the POS transaction.
The response holds until the transaction is accepted by the terminal device or times out, reducing the number of API calls.


**Polling to get the transaction results:**

* **Short polling:** Poll GET with `waitForTransactionProcessing: false` when you want to check the transaction status at your own interval.
* **Long polling:** Poll GET with `waitForTransactionProcessing: true` to hold the request until the transaction reaches a final status, reducing the number of API calls.


## Transaction Status Lifecycle

| ID | Status | Final? | Description |
|  --- | --- | --- | --- |
| 1 | TerminalConnecting | No | Transaction sent to the terminal. Waiting for the terminal to accept. |
| 2 | TransactionProcessing | No | Terminal accepted the transaction and is processing the card. |
| 6 | Completed | Yes | Transaction processed successfully. |
| 3 | DeclinedByProcessor | Yes | The payment processor declined the transaction. |
| 4 | CancelByPos | Yes | Your POS application cancelled the transaction. |
| 5 | CancelByTerminal | Yes | The transaction was cancelled at the terminal (e.g. customer pressed cancel). |
| 9 | TerminalOffline | Yes | The terminal could not be reached. |
| 7 | Error | Yes | A system error occurred during processing. |
| 8 | Inconsistency | Yes | A data mismatch occurred between the POS and terminal. |
| 10 | TransactionSentToProcessor | No | Card data submitted to the payment processor. |


Check the `isCompleted` field to determine if the transaction has reached a final status.

## Error Responses

All endpoints return standard HTTP status codes:

| Status Code | Description |
|  --- | --- |
| 400 Bad Request | Invalid request. Check that required fields are present and correctly formatted. |
| 401 Unauthorized | Missing or invalid API token. |
| 403 Forbidden | Your account does not have the required POS permission. |
| 404 Not Found | The specified transaction or terminal was not found. |
| 500 Internal Server Error | An unexpected error occurred. Contact support if the issue persists. |