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

# Process Payment

> Process an NFC card payment at a POS terminal

<Info>
  Main endpoint for processing purchases. POS routes use HMAC authentication, not bearer tokens.
</Info>

<Note>
  `fee_amount` reflects the effective fee resolved for the transaction. If your fee configuration charges the subscriber or the processor for POS payments, that configured value is returned here instead of always being `0.00`.
</Note>

## Request

<ParamField header="X-API-Key-ID" type="string" required>
  API key ID assigned to the POS integration
</ParamField>

<ParamField header="X-Timestamp" type="string" required>
  RFC3339 timestamp used in the HMAC signature (example: `2026-03-10T12:00:00Z`)
</ParamField>

<ParamField header="X-Signature" type="string" required>
  Hex-encoded HMAC-SHA256 of `METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + BODY`
</ParamField>

### Body Parameters

<ParamField body="card_serial" type="string" required>
  Card serial number read from NFC
</ParamField>

<ParamField body="merchant_id" type="string" required>
  Registered merchant identifier
</ParamField>

<ParamField body="merchant_name" type="string">
  Merchant display name shown on receipts; defaults to `merchant_id` when omitted
</ParamField>

<ParamField body="terminal_id" type="string" required>
  Terminal identifier
</ParamField>

<ParamField body="amount" type="string" required>
  Payment amount (e.g., `500.00`)
</ParamField>

<ParamField body="currency" type="string" required default="SLE">
  Currency code
</ParamField>

<ParamField body="pin" type="string" required>
  Customer's 4-digit PIN
</ParamField>

<ParamField body="transaction_ref" type="string" required>
  Merchant's unique transaction reference
</ParamField>

<ParamField body="processor_id" type="string" required>
  Processor account ID that receives the funds
</ParamField>

***

## Response

<ResponseField name="success" type="boolean">
  Whether payment was approved
</ResponseField>

<ResponseField name="transaction_id" type="string">
  OLIVE transaction ID
</ResponseField>

<ResponseField name="approval_code" type="string">
  Approval code for the successful payment
</ResponseField>

<ResponseField name="amount" type="string">
  Formatted transaction amount
</ResponseField>

<ResponseField name="remaining_balance" type="string">
  Formatted remaining card balance
</ResponseField>

<ResponseField name="fee_amount" type="string">
  Formatted effective fee charged for the transaction based on the active POS fee configuration
</ResponseField>

***

## Examples

<RequestExample>
  ```bash cURL theme={null}
  BODY='{"card_serial":"OLIV0001","merchant_id":"MERCH_XYZ","merchant_name":"Supermart Ltd","terminal_id":"TERM_001","amount":"1500.00","currency":"SLE","pin":"1234","transaction_ref":"ORDER-998877","processor_id":"proc-uuid-123"}'
  TIMESTAMP='2026-03-10T12:00:00Z'
  SIGNATURE=$(printf 'POST\n/api/v1/pos/payment\n%s\n%s' "$TIMESTAMP" "$BODY" | openssl dgst -sha256 -hmac "$OLIVE_HMAC_SECRET" -hex | sed 's/^.* //')

  curl -X POST "https://demo.api.vultlocal.com/api/v1/pos/payment" \
    -H "X-API-Key-ID: $OLIVE_API_KEY_ID" \
    -H "X-Timestamp: $TIMESTAMP" \
    -H "X-Signature: $SIGNATURE" \
    -H "Content-Type: application/json" \
    -d "$BODY"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 Approved theme={null}
  {
    "success": true,
    "message": "Payment successful",
    "transaction_id": "txn_pos_12345",
    "approval_code": "882211",
    "amount": "1,500.00 SLE",
    "remaining_balance": "48,500.00 SLE",
    "fee_amount": "15.00 SLE"
  }
  ```

  ```json 400 Declined theme={null}
  {
    "success": false,
    "error": "Insufficient funds"
  }
  ```

  ```json 400 Invalid PIN theme={null}
  {
    "success": false,
    "error": "Invalid PIN"
  }
  ```
</ResponseExample>

***

## Errors

| Status | Code                         | Description                                                     |
| ------ | ---------------------------- | --------------------------------------------------------------- |
| 400    | Validation or business error | Invalid payload, declined transaction, or bad PIN               |
| 401    | HMAC auth error              | Missing/invalid `X-API-Key-ID`, `X-Timestamp`, or `X-Signature` |
| 500    | Internal error               | Server or downstream processor failure                          |


## OpenAPI

````yaml olive-openapi.json POST /pos/payment
openapi: 3.0.0
info:
  description: >-
    API Gateway for OLIVE NFC Card Payment System - Comprehensive payment, card
    management, agent operations, and admin authentication. All /api/v1 routes
    require authentication using either API Key or JWT token.
  title: OLIVE NFC Card Payment API
  termsOfService: http://swagger.io/terms/
  contact:
    name: API Support
    email: support@olive.sl
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: 1.0.0
servers:
  - url: https://olive-gateway-a6ba.onrender.com/api/v1
security: []
paths:
  /pos/payment:
    post:
      tags:
        - POS
      summary: Process POS payment
      description: Process NFC card payment at Smart PAY POS terminal
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/handler.AppPaymentRequest'
        description: POS payment details
        required: true
      responses:
        '200':
          description: Payment approved
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          description: Payment declined
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
components:
  schemas:
    handler.AppPaymentRequest:
      type: object
      required:
        - amount
        - card_serial
        - currency
        - merchant_id
        - processor_id
        - transaction_ref
      properties:
        amount:
          description: Accepts decimal format like "150.00" or "150"
          type: string
          example: '150.00'
        card_serial:
          description: 'Supports any alphanumeric: CARD0001, 48290173K, etc.'
          type: string
          example: CARD0001
        currency:
          type: string
          example: SLE
        merchant_id:
          type: string
          example: MERCHANT001
        merchant_name:
          description: Display name for receipts
          type: string
          example: ABC Store
        metadata:
          type: object
          additionalProperties: true
        processor_id:
          description: Processor account that receives the funds
          type: string
          example: proc-uuid-123
        transaction_ref:
          type: string
          example: APP-TXN-123

````