Create a payment¶
createPayment charges a payment method. You need a paymentMethodId — either a fresh token from
the card or bank SDK, or a
saved payment method.
Headers¶
Send the standard three plus an idempotency key — createPayment will
not run without one:
{
"x-aptean-apim": "<your api key>",
"x-aptean-tenant": "<your tenant id>",
"x-aptean-tenant-secret": "<your tenant secret>",
"idempotency-key": "<a unique value you generate>"
}
The mutation¶
mutation CreatePayment($input: CreatePaymentInput!) {
createPayment(input: $input) {
code
message
payment {
id
status
pendingReasonCode
failureReason
}
}
}
Variables¶
{
"input": {
"paymentMethodId": "<token or saved payment method id>",
"amount": 1250,
"currency": "USD",
"immediateCapture": true,
"riskMetadata": {
"address": {
"postalCode": "30328",
"country": "US"
},
"phone": {
"countryCode": "1",
"number": "5551234567"
},
"lineItems": []
}
}
}
Warning
amount is in the currency's lowest denomination. 1250 is $12.50. This is the
most common integration bug in Aptean Pay, and it is silent — the payment succeeds, for the wrong
amount.
Required fields¶
| Field | Type | Notes |
|---|---|---|
paymentMethodId |
String | The token or saved payment method to charge. |
amount |
Int | Minor units. 1250 = $12.50. |
currency |
CurrencyType |
USD or CAD. |
immediateCapture |
Boolean | true charges now. false creates a pre-authorisation — see Pre-authorise and capture. |
riskMetadata |
Object | Required. Must contain address, phone and lineItems (an empty array is acceptable). |
Fields worth knowing about¶
| Field | Type | Notes |
|---|---|---|
description |
String | Free text shown on the payment. |
invoiceNumber, orderNumber, customerPONumber |
String | Your own references. Set these — they are what makes a payment findable later, and what reconciliation depends on. |
customerId / customerNumber |
String | Associates the payment with a customer. |
paymentRequestId / paymentRequestAllocation |
— | Use when settling an existing payment request. |
creditAmount |
Int | Applies a credit memo to this payment. |
convenienceFee, amountBeforeFees |
Int | Only if convenience fees are enabled for your tenant. |
failOnReview |
Boolean | true fails the payment outright rather than letting it go to risk review. |
captureAt |
Date | Schedule a later capture instead of capturing now. |
customData |
JSON | Arbitrary key–value pairs stored against the payment. |
Tip
riskMetadata.lineItems accepts { description, price, currency, quantity } with price
also in minor units. Populating it genuinely helps: better fraud scoring, and Level 2/Level 3 card
data can reduce interchange on commercial cards.
Run it¶
- Open the GraphQL playground (staging only).
- Paste your headers into the HTTP HEADERS tab.
- Paste the mutation into the query pane and the variables into QUERY VARIABLES.
- Run it.
The response¶
{
"data": {
"createPayment": {
"code": "SUCCESS",
"message": "Payment created.",
"payment": {
"id": "300f5a49-68f0-44a0-8f73-d2f42ced4a90",
"status": "COMPLETED",
"pendingReasonCode": null,
"failureReason": null
}
}
}
}
Store payment.id. You need it to capture,
cancel or refund the payment, and to check its status
later. If you do not persist it, you have no handle on the money you just moved.
Note
code: "SUCCESS" means the instruction was accepted — it does not always mean
settled funds. Check payment.status. A card payment usually comes back COMPLETED; ACH comes
back PENDING and can still fail days later. See Payment status.
Common failures¶
| Message | Cause |
|---|---|
idempotency key is required |
No idempotency-key header. |
idempotency key has already been used, a unique key must be provided |
An earlier call with that key succeeded. Find that payment; do not retry with a new key. See Idempotency. |
Field "riskMetadata" of required type "RiskMetadataPaymentInput!" was not provided. |
riskMetadata is mandatory, including address, phone and lineItems. |
Response not successful: Received status code 400 |
An authentication header is wrong. See Errors. |
Full list: Errors.