> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.paywithatoa.co.uk/llms.txt
> Use this file to discover all available pages before exploring further.

# Process Remote Payment

> Trigger a payment on a merchant's own PAX terminal remotely through the Atoa API, and track it to completion using webhooks.

Creates a remote payment request and notifies a POS terminal so it can present the payment to the customer. The merchant is resolved from the SDK API key you authenticate with.

Pick the target terminal with [List Terminals](/api-reference/RemotePayments/list-terminals) and pass its `id`. On success the endpoint returns a `paymentRequestId` you can use to track the payment.

<Note>
  The whole payment is assembled server-side. Fields such as the customer id,
  order id, expiry, tips, retry and split behaviour, store and terminal
  binding, and environment are all set by Atoa. Only the fields documented
  below are read from your request; any other field in the body is ignored.
</Note>

### Authorization

Bearer `<token>`

**Body Parameters**

<ParamField body="id" type="string" required>
  The `id` of the POS terminal that should receive the payment, as returned by
  [List Terminals](/api-reference/RemotePayments/list-terminals). The terminal
  must belong to the authenticated merchant, have a registered
  push-notification device (`tokenMissing: false`), and have remote payments
  enabled.
</ParamField>

<ParamField body="amount" type="number" required>
  The amount to charge. Must have at most 2 decimal places.
</ParamField>

<ParamField body="paymentMethod" type="string">
  Controls the set of payment methods shown to the customer on the terminal. If not specified, the terminal defaults to offering all payment methods enabled on the merchant account.

  <Accordion title="Possible enum values">
    * `PAY_BY_BANK` – When provided, only Pay by Bank will be shown to the customer.

    * `CARD` – When provided, only card payment will be shown to the customer. If card is not enabled in your account please contact support.

    * If omitted or set to any other value, both options are displayed, allowing the customer to choose their preferred payment method.
  </Accordion>
</ParamField>

<ParamField body="notes" type="string">
  Optional note shown to the customer. Trimmed of surrounding whitespace and must
  not exceed 30 characters.
</ParamField>

<ParamField body="consumerDetails" type="object">
  Optional customer details, saved as a consumer record and linked to this
  payment. When both `phoneCountryCode` and `phoneNumber` are supplied the phone
  number is validated.

  <Expandable title="consumerDetails">
    <ParamField body="phoneCountryCode" type="string">
      Customer phone country code, e.g. `+44`.
    </ParamField>

    <ParamField body="phoneNumber" type="string">
      Customer phone number.
    </ParamField>

    <ParamField body="email" type="string">
      Customer email address.
    </ParamField>

    <ParamField body="firstName" type="string">
      Customer first name.
    </ParamField>

    <ParamField body="lastName" type="string">
      Customer last name.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="metadata" type="object">
  Set of key-value pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format.

  * Up to **50** key-value pairs.
  * Each key must be **1–40** characters and must not contain `[` or `]`.
  * Each value must be a **string** of at most **500** characters.

  Once set, metadata is returned in the [Get Transactions](/api-reference/Payment/get-transactions), [Get Payout Transactions](/api-reference/Payouts/getPayoutTransactions), and [Get Payment Status](/api-reference/Payment/getPaymentStatus) responses, and is included in the [POS Payment Status Webhook](/api-reference/Webhook/posPaymentStatusWebhookResponse).

  <Info>Metadata is frozen when the payment is created and cannot be changed afterwards. An empty object (`{}`) is treated as no metadata.</Info>
</ParamField>

**Response**

<ResponseField name="paymentRequestId" type="string" required>
  The identifier (UUID) of the created payment request. Use it to track the
  payment via the payment-status endpoint or the `POS_PAYMENT_STATUS` webhook.
</ResponseField>

### What happens next

The target terminal prompts the customer to complete the payment. To track the
outcome, poll [Get Payment Status](/api-reference/Payment/getPaymentStatus) with
the returned `paymentRequestId`, and/or subscribe to the
[`POS_PAYMENT_STATUS` webhook](/api-reference/Webhook/posPaymentStatusWebhookResponse).
Receiving webhooks requires a `whsec_` signing secret configured for your
endpoint.

If you're experiencing issues, please check the [Troubleshooting](/remote-payments#troubleshooting)
section.

**Errors**

| Status | When                                                                                                                                                                |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Missing `id`, remote payments not enabled for the merchant or the terminal, terminal not configured for push notifications, or `notes` over the 30-character limit. |
| `401`  | Missing or invalid API key.                                                                                                                                         |
| `404`  | Terminal not found, or not owned by the authenticated merchant.                                                                                                     |
| `500`  | Unexpected internal error.                                                                                                                                          |

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://api.atoa.me/api/terminal/process-remote-payment' \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
      "id": "1",
      "amount": 42.50,
      "paymentMethod": "PAY_BY_BANK",
      "notes": "Table 12",
      "consumerDetails": {
        "phoneCountryCode": "+44",
        "phoneNumber": "7700900123",
        "email": "customer@example.com",
        "firstName": "Alex",
        "lastName": "Doe"
      },
      "metadata": {
        "bookingId": "BK-42427",
        "orderReference": "ORD-1"
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  url = "https://api.atoa.me/api/terminal/process-remote-payment"
  headers = {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json",
  }
  payload = {
      "id": "1",
      "amount": 42.50,
      "paymentMethod": "PAY_BY_BANK",
      "notes": "Table 12",
      "consumerDetails": {
          "phoneCountryCode": "+44",
          "phoneNumber": "7700900123",
          "email": "customer@example.com",
          "firstName": "Alex",
          "lastName": "Doe",
      },
      "metadata": {
          "bookingId": "BK-42427",
          "orderReference": "ORD-1",
      },
  }

  response = requests.post(url, json=payload, headers=headers)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://api.atoa.me/api/terminal/process-remote-payment",
    {
      method: "POST",
      headers: {
        Authorization: "Bearer <token>",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        id: "1",
        amount: 42.5,
        paymentMethod: "PAY_BY_BANK",
        notes: "Table 12",
        consumerDetails: {
          phoneCountryCode: "+44",
          phoneNumber: "7700900123",
          email: "customer@example.com",
          firstName: "Alex",
          lastName: "Doe",
        },
        metadata: {
          bookingId: "BK-42427",
          orderReference: "ORD-1",
        },
      }),
    }
  );

  const data = await response.json();
  console.log(data);
  ```

  ```php PHP theme={null}
  <?php

  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.atoa.me/api/terminal/process-remote-payment",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => json_encode([
      "id" => "1",
      "amount" => 42.50,
      "paymentMethod" => "PAY_BY_BANK",
      "notes" => "Table 12",
      "consumerDetails" => [
        "phoneCountryCode" => "+44",
        "phoneNumber" => "7700900123",
        "email" => "customer@example.com",
        "firstName" => "Alex",
        "lastName" => "Doe"
      ],
      "metadata" => [
        "bookingId" => "BK-42427",
        "orderReference" => "ORD-1"
      ]
    ]),
    CURLOPT_HTTPHEADER => [
      "Authorization: Bearer <token>",
      "Content-Type: application/json"
    ],
  ]);

  $response = curl_exec($curl);
  curl_close($curl);
  echo $response;
  ```

  ```go Go theme={null}
  package main

  import (
    "bytes"
    "fmt"
    "io/ioutil"
    "net/http"
  )

  func main() {
    url := "https://api.atoa.me/api/terminal/process-remote-payment"
    payload := []byte(`{
      "id": "1",
      "amount": 42.50,
      "paymentMethod": "PAY_BY_BANK",
      "notes": "Table 12",
      "metadata": {
        "bookingId": "BK-42427",
        "orderReference": "ORD-1"
      }
    }`)

    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(payload))
    req.Header.Add("Authorization", "Bearer <token>")
    req.Header.Add("Content-Type", "application/json")

    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)
    fmt.Println(string(body))
  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.post("https://api.atoa.me/api/terminal/process-remote-payment")
    .header("Authorization", "Bearer <token>")
    .header("Content-Type", "application/json")
    .body("{\"id\":\"1\",\"amount\":42.50,\"paymentMethod\":\"PAY_BY_BANK\",\"notes\":\"Table 12\",\"metadata\":{\"bookingId\":\"BK-42427\",\"orderReference\":\"ORD-1\"}}")
    .asString();
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "paymentRequestId": "3f2504e0-4f89-41d3-9a0c-0305e82c3301"
  }
  ```

  ```json 400 theme={null}
  {
    "name": "BAD_REQUEST",
    "message": "Remote payments are not enabled for this merchant.",
    "status": 400,
    "errors": "[]"
  }
  ```

  ```json 401 theme={null}
  {
    "name": "UNAUTHORIZED",
    "message": "Unauthorized",
    "status": 401,
    "errors": "[]"
  }
  ```

  ```json 404 theme={null}
  {
    "name": "NOT_FOUND",
    "message": "Terminal not found",
    "status": 404,
    "errors": "[]"
  }
  ```

  ```json 500 theme={null}
  {
    "name": "INTERNAL_SERVER_ERROR",
    "message": "Internal Server Error",
    "status": 500,
    "errors": "[]"
  }
  ```
</ResponseExample>
