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

# Payments

> Initiate and manage Raast pay-ins using aggregator merchants.

Payments initiate a Request-to-Pay (RTP) against a customer's bank account. Each payment belongs to an [aggregator merchant](/concepts/merchant) and uses the Raast network to settle instantly once the customer approves.

### Endpoint summary

* **Method & path**: `POST /v1/aggregators/{{aggregator_id}}/payments`
* **Authentication**: `X-SFPY-AGGREGATOR-SECRET-KEY: {{secret_key}}`
* **Idempotency**: Provide a unique `request_id` and reuse it when retrying the same intent.

| Field                            | Type    | Required?              | Notes                                         |
| -------------------------------- | ------- | ---------------------- | --------------------------------------------- |
| `request_id`                     | string  | Yes                    | UUID that enforces idempotency.               |
| `amount`                         | integer | Yes                    | Amount in paisa (PKR).                        |
| `aggregator_merchant_identifier` | string  | Yes                    | Token returned when you created the merchant. |
| `order_id`                       | string  | Yes                    | Merchant order reference.                     |
| `type`                           | enum    | Yes                    | `RTP_NOW` or `RTP_LATER`.                     |
| `expiry_in_minutes`              | integer | Required for RTP Now   | Range 1-180 minutes.                          |
| `expiry_in_days`                 | integer | Required for RTP Later | Range 1-40 days.                              |
| `debitor_iban`                   | string  | One of                 | Provide IBAN when you know the account.       |
| `debitor_raast_id`               | string  | One of                 | Provide Raast alias (for example, phone).     |
| `debitor_vault_token`            | string  | One of                 | Provide stored vault token.                   |

<Callout type="tip">Validate the debtor's IBAN or alias with the [account validation utilities](/concepts/account-validation) before creating the payment.</Callout>

### Example request

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST "{{base_url}}/v1/aggregators/{{aggregator_id}}/payments" \
    --header "X-SFPY-AGGREGATOR-SECRET-KEY: {{secret_key}}" \
    --header "Content-Type: application/json" \
    --data '{
      "request_id": "{{request_id}}",
      "amount": 7500,
      "aggregator_merchant_identifier": "{{aggregator_merchant_identifier}}",
      "order_id": "ORDER-2025-042",
      "type": "RTP_NOW",
      "expiry_in_minutes": 30,
      "debitor_iban": "PK36SCBL0000001123456702"
    }'
  ```

  ```typescript TypeScript theme={null}
  type CreatePaymentPayload = {
    api_version: string;
    data: {
      token: string;
      status: 'P_INITIATED' | 'P_RECEIVED' | 'P_FAILED' | 'P_REJECTED' | 'P_SETTLED';
      request_id: string;
      order_id: string;
      trace_reference?: string;
      msg_id?: string;
      created_at: string;
    };
  };

  const aggregatorMerchantIdentifier = process.env.SAFEPAY_AGGREGATOR_MERCHANT_IDENTIFIER;
  if (!aggregatorMerchantIdentifier) {
    throw new Error('Missing SAFEPAY_AGGREGATOR_MERCHANT_IDENTIFIER');
  }

  const paymentResponse = await fetch(
    `${process.env.SAFEPAY_BASE_URL}/v1/aggregators/${process.env.SAFEPAY_AGGREGATOR_ID}/payments`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-SFPY-AGGREGATOR-SECRET-KEY': process.env.SAFEPAY_SECRET_KEY ?? '',
      },
      body: JSON.stringify({
        request_id: crypto.randomUUID(),
        amount: 7500,
        aggregator_merchant_identifier: aggregatorMerchantIdentifier,
        order_id: 'ORDER-2025-042',
        type: 'RTP_NOW',
        expiry_in_minutes: 30,
        debitor_iban: 'PK36SCBL0000001123456702',
      }),
    },
  );

  if (!paymentResponse.ok) {
    const error = await paymentResponse.json();
    throw new Error(`Payment failed: ${paymentResponse.status} ${error.message}`);
  }

  const paymentPayload: CreatePaymentPayload = await paymentResponse.json();
  console.log('Payment status', paymentPayload.data.status);
  ```
</CodeGroup>

### Status lifecycle

| Status                 | Description                                          |
| ---------------------- | ---------------------------------------------------- |
| `P_INITIATED`          | Safepay accepted the request and pushed it to Raast. |
| `P_RECEIVED`           | Customer approval pending.                           |
| `P_AUTHORIZED`         | Payment authorized and funds on hold.                |
| `P_CAPTURED`           | Payment captured successfully.                       |
| `P_SETTLED`            | Funds transferred. Emit confirmation to the user.    |
| `P_FAILED`             | Payment failed during processing.                    |
| `P_REJECTED`           | Customer declined or request rejected.               |
| `P_CANCELLED`          | Payment was canceled before completion.              |
| `P_REVERSED`           | Payment reversed after completion.                   |
| `P_PARTIALLY_REFUNDED` | Payment partially refunded.                          |
| `P_REFUNDED`           | Payment fully refunded.                              |

### Monitoring

* Poll `GET /v1/aggregators/{{aggregator_id}}/payments/{{payment_id}}` for dashboards.
* Subscribe to [webhooks](/concepts/webhooks) to receive final states.
* Use `request_id` to deduplicate retries.

## Key endpoints

| Endpoint                                                        | Purpose                                    |
| --------------------------------------------------------------- | ------------------------------------------ |
| `POST /v1/aggregators/{{aggregator_id}}/payments`               | Create RTP Now or RTP Later payments.      |
| `GET /v1/aggregators/{{aggregator_id}}/payments`                | List payments with filters and pagination. |
| `GET /v1/aggregators/{{aggregator_id}}/payments/{{payment_id}}` | Read a single payment.                     |

## See also

* [Payment types](/concepts/payment-types)
* [RTP Now use case](/use-cases/rtp_now)
* [RTP Later use case](/use-cases/rtp_later)
* [Webhooks](/concepts/webhooks)
