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

request_id
string
required
UUID that keeps the scheduled Request To Pay idempotent.
amount
integer
required
Amount in paisa. 22000 equals PKR 220.00.
aggregator_merchant_identifier
string
required
Token returned when you created the merchant.
order_id
string
required
Merchant order reference used for reconciliation.
type
string
required
Set to RTP_LATER.
expiry_in_days
integer
required
Approval window in days (1-40).
debitor_raast_id
string
Provide when requesting via a Raast alias. One of the debtor identifiers must be supplied.
debitor_iban
string
Use when you know the debtor’s IBAN instead of a Raast ID. One of the debtor identifiers must be supplied.
debitor_vault_token
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
curl --request GET "{{base_url}}/v1/aggregators/{{aggregator_id}}/payments/{{payment_token}}" \
  --header "X-SFPY-AGGREGATOR-SECRET-KEY: {{secret_key}}"

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