Skip to main content
Use this flow when customers may approve hours or days after you submit the payment, such as invoice settlements or subscription renewals.

Prerequisites

  • {{aggregator_id}} and {{secret_key}}
  • aggregator_merchant_identifier for the merchant collecting funds
  • Debtor IBAN or Raast ID

Flow summary

1

Load merchant identifiers

Retrieve the aggregator_merchant_identifier from the merchant creation response.
2

Validate the debtor account

Use the account validation utilities to confirm the debtor details.
3

Create the RTP Later payment

Submit POST /v1/aggregators/{{aggregator_id}}/payments with type: RTP_LATER and an expiry window.
4

Track the outcome

Use webhooks (and optional polling) to surface the final payment status.
Set {{base_url}} to https://dev.api.getsafepay.com/raastwire in Sandbox or https://api.getsafepay.com/raastwire in Production.

RTP later

string
required
UUID that keeps the scheduled Request To Pay idempotent.
integer
required
Amount in paisa. 22000 equals PKR 220.00.
string
required
Token returned when you created the merchant.
string
required
Merchant order reference used for reconciliation.
string
required
Set to RTP_LATER.
integer
required
Approval window in days (1-40).
string
Provide when requesting via a Raast alias. One of the debtor identifiers must be supplied.
string
Use when you know the debtor’s IBAN instead of a Raast ID. One of the debtor identifiers must be supplied.
string
Reference a stored payment method for recurring requests. One of the debtor identifiers must be supplied.

Monitor status

Use webhooks as the primary source of truth. Polling is helpful for dashboards or fallback workflows.
cURL

Webhook events to expect

  • payment.created
  • payment.pending_authorization
  • payment.authorized
  • payment.completed
  • payment.settled
  • payment.rejected
  • payment.failed
  • payment.voided
  • payment.reversed
  • payment.refunded (if you issue refunds)
  • payment.refund_partial (if you issue partial refunds)
When the webhook indicates payment.settled, mark the invoice paid. If the customer rejects, resend with a new request_id after you resolve the issue.

Troubleshooting

  • Expired request - Regenerate the RTP with a fresh request_id and expiry_in_days.
  • No response yet - Offer manual refresh or status polling for long-lived requests.
  • Duplicate payload - Reusing a request_id with different parameters returns an idempotency error; retry with the same body.

See also