Payment requests¶
A payment request is an invoice you send to the payer. Aptean Pay emails or texts them a link, they pay it in the payer portal, and you never touch their card details.
This is the opposite flow to Create a payment. There, you hold the payment method and charge it. Here, the payer holds it and chooses when to pay.
Two variants¶
| Mutation | Use when |
|---|---|
upsertPaymentRequest |
You have an invoice PDF to attach. Requires an upload first. |
upsertPaymentRequestNoInvoice |
You have no PDF — just an amount, and optionally line items. |
Headers¶
The standard three. No idempotency key is required — uniqueness is
enforced by referenceNumber instead.
{
"x-aptean-apim": "<your api key>",
"x-aptean-tenant": "<your tenant id>",
"x-aptean-tenant-secret": "<your tenant secret>"
}
With an invoice¶
Step 1 — upload the invoice¶
The upload mutation takes a file, so it is a GraphQL multipart request. The playground cannot
send files; use Postman, curl, or your own code.
In Postman:
- Method POST, URL = your Merchant API host (e.g.
https://stg.api.apteanpay.com/). - Under Headers, add your three authentication headers.
- Under Body, choose form-data, and add these three fields:
| Key | Type | Value |
|---|---|---|
operations |
Text | {"query": "mutation($file: Upload!){ upload(input:{ file: $file}){ uniqueId message code } }"} |
map |
Text | {"0":["variables.file"]} |
0 |
File | Select your PDF. |
Warning
The third field's key is the literal character 0, and its type must be File,
not Text. This trips up almost everyone the first time.
- Send it, then copy
uniqueIdfrom the response. That is yourinvoiceRef.
Step 2 — create the payment request¶
mutation UpsertPaymentRequest($input: UpsertPaymentRequestInput!) {
upsertPaymentRequest(input: $input) {
code
message
error
paymentRequestId
paymentUrl
}
}
{
"input": {
"referenceNumber": "INV-10042",
"invoiceRef": "<the uniqueId from step 1>",
"type": "EMAIL",
"email": "payer@example.com",
"amount": 12500
}
}
Tip
To attach several invoices to one request, use invoiceRefs — an array of upload ids,
up to 100 — instead of invoiceRef. Upload each PDF separately and collect the ids.
Without an invoice¶
mutation UpsertPaymentRequestNoInvoice($input: UpsertPaymentRequestNoInvoiceInput!) {
upsertPaymentRequestNoInvoice(input: $input) {
code
message
error
paymentRequestId
paymentUrl
}
}
{
"input": {
"referenceNumber": "INV-10043",
"type": "EMAIL_AND_SMS",
"email": "payer@example.com",
"phoneNumber": "+14155552671",
"amount": 12500,
"orderLineItems": [
{
"description": "Annual support",
"price": 12500,
"currency": "USD",
"quantity": 1
}
]
}
}
The fields¶
| Field | Type | Notes |
|---|---|---|
referenceNumber |
String | Must be unique for your tenant. Usually your invoice number. |
amount |
Int | Minor units. Minimum 100 (1.00). |
type |
CommunicationType |
EMAIL, SMS, EMAIL_AND_SMS, or NONE. |
email |
String | Required when type includes email. |
phoneNumber |
String | Required when type includes SMS. E.164 format — +14155552671. |
id |
ID | Supply to update an existing request rather than create one. |
status, statusReason |
— | Update the request's status. |
sendCommunication |
Boolean | Whether Aptean Pay sends the notification. |
invoiceRef / invoiceRefs |
String / [String] | upsertPaymentRequest only. One id, or up to 100. |
orderLineItems |
[Object] | upsertPaymentRequestNoInvoice only. { description, price, currency, quantity }, price in minor units. |
Note
type: "NONE" creates the request and sends nothing. Use it when you want to deliver
the paymentUrl yourself — in your own email, portal or statement.
It is an upsert, not a create¶
The mutation name is not decoration. Pass id and you update the existing request. Omit id and
you create a new one — and if referenceNumber is already taken, the call fails rather than
silently updating.
The response¶
{
"data": {
"upsertPaymentRequest": {
"code": "SUCCESS",
"message": "payment request created",
"error": null,
"paymentUrl": "https://stg.payer.apteanpay.com/?MDk4NWMyMzAz…",
"paymentRequestId": "f8aa508c-bfae-4cae-a197-21b78a92ee38"
}
}
}
paymentRequestId— store this. It is your handle on the request.paymentUrl— the payer's payment link. Aptean Pay has already sent it iftypewas notNONE; this is the same link, for you to store or resend.
Warning
paymentUrl contains a token that lets whoever holds it pay this invoice. Treat it
as sensitive. Do not log it, and do not put it anywhere it could be indexed or shared onward.
Common failures¶
| Message | Cause |
|---|---|
unable to create payment request, reference number already exists |
referenceNumber must be unique. Pass id if you meant to update. |
unable to create payment request, amount must be greater than $1 |
Minimum is 100 minor units. |
unable to create payment request, uploaded invoice not found |
invoiceRef is not a uniqueId from a successful upload. |
unable to create payment request, {field} is required |
That field was not supplied. |
email is required for email communications |
type includes email but email was omitted. |
Variable "$type" got invalid value …; Expected type CommunicationType. |
type must be exactly EMAIL, SMS, EMAIL_AND_SMS or NONE. |
Context creation failed: FORBIDDEN [2] |
x-aptean-apim is not valid. |
Context creation failed: FORBIDDEN [4] |
x-aptean-tenant-secret is not correct. |