Apex API for developers
Everything the REDA Pay screens do is also available to Apex in your org through one global class. Use it when a flow is not enough: a custom payment page, a migration script that registers existing customers with Payload, an integration that must process an order and read the result synchronously.
- You are a Salesforce developer with the Author Apex permission, working in a sandbox against Payload's test environment.
- The running user needs the REDA Pay permission set for the operation (Admin User for setup operations; Transaction Manager for void and refund) and, for disbursements, REDA Pay - Enable Disbursements.
- Every method makes a callout to Payload. Call them from a context that allows callouts (a future, queueable or batch method, or a controller with no pending uncommitted work).
The class
All methods are static on rpay.PayAPIGlobal and return an rpay.TransactionResult.
| Method | What it does |
|---|---|
createPayCustomer(Id payCustomerId) | Registers the Pay Customer with Payload and stores the customer identifier |
updatePayCustomer(Id payCustomerId) | Sends the customer's name, email and phone to Payload |
createPayMethod(Id payMethodId, rpay.PayMethodWrapper details) | Registers a card or bank account for an existing Pay Method record and stores the token and descriptive details |
deletePayMethod(Id payMethodId) | Removes the method at Payload; the record stays, marked deleted |
processPayOrder(Id payOrderId, rpay.PayMethodWrapper details) | Processes an Immediate order. Pass details to register a new card or account on the way, or null to use the order's registered Pay Method |
voidTransaction(Id transactionId, Date voidedDate, String voidingReason) | Voids a processed, unfunded transaction |
refundTransaction(Id transactionId, Decimal refundAmount, String description, Date refundDate) | Refunds a processed payment, fully or partially, creating a refund transaction |
syncTransaction(Id transactionId) | Re-reads one transaction from Payload |
syncPayOrderTransactions(Id payOrderId) | Reads every transaction Payload holds for the order; updates and creates as needed |
Two older signatures, voidTransaction(Id) and refundTransaction(Id, Decimal, String), still compile but throw "This method is deprecated. Please follow the documentation for updated method details." Use the full ones.
rpay.PayMethodWrapper
The card or bank details for createPayMethod and processPayOrder:
| Field | Card | Bank account |
|---|---|---|
methodType | card | bank_account |
cardNumber, cardHolderName, cardCVV, cardExpiry (MM/YY), cardType | ✓ | |
accountName, accountNumber, routingNumber (9 digits), accountType, accountClass, accountCurrency | ✓ | |
postalCode | ✓ | ✓ |
These values pass through your Apex to Payload and are never stored — see Security and card data. Do not log them, store them in fields, or put them in debug statements.
rpay.TransactionResult
| Field | Meaning |
|---|---|
isSuccess | Whether the operation succeeded |
error_message | The reason when it did not |
payorder_name, payorder_sfid | The order's number and Id |
transaction_id, transaction_ref, transaction_sfid, transaction_obj | Payload's transaction identifier and reference, and the Pay Transaction record |
customer_id, customer | Payload's customer identifier and the Pay Customer record |
pay_method_id, pay_method_description, isDefaultMethod, card_name, card_last4, card_brand, card_type, card_exp_month, card_exp_year | The registered method's token and descriptive details |
A few further fields (identification_number, identification_type, external_url, the three_d_secure_mode group) exist for future use and are not populated in this release.
Example: process an order with a saved method
// The Pay Order exists, is Immediate, unprocessed, and already has an active Pay Method.
rpay.TransactionResult r = rpay.PayAPIGlobal.processPayOrder(payOrderId, null);
if (r.isSuccess) {
System.debug('Processed ' + r.payorder_name + ' as ' + r.transaction_ref);
} else {
System.debug('Failed: ' + r.error_message); // a failed Pay Transaction has been saved under the order
}
Example: register a bank account for a vendor
rpay.PayMethodWrapper w = new rpay.PayMethodWrapper();
w.methodType = 'bank_account';
w.accountName = 'Harbor Maintenance LLC';
w.accountNumber = accountNumberFromYourSecureInput; // never hard-code or log this
w.routingNumber = '021000021';
w.accountType = 'checking';
w.accountClass = 'business';
w.accountCurrency = 'USD';
w.postalCode = '33602';
// payMethodId is a Pay Method record created with Pay Customer, Pay Profile,
// Pay Method Type = bank_account and Transfer Type = receive-only (disbursement).
rpay.TransactionResult r = rpay.PayAPIGlobal.createPayMethod(payMethodId, w);
Rules that apply to API calls too
- The same validations as the screens: the profile and account must be active, the customer, account and method must allow the transfer type and method type, the running user must be allowed the direction, and a processed order cannot be processed again. Violations come back in
error_message. - Convenience fees are calculated when the order is saved, from the account's Fee Setups; set Zero Convenience Fee or Convenience Fee Override on the order before processing if needed.
- Methods call Payload one record at a time. Loop in your code with care for callout limits, or hand bulk work to a batch.
processPayOrderwithdetailsregisters the method before charging, so a card registered this way is kept for reuse unless you untick Keep Active afterwards.
The scheduler class
rpay.SchedulePayOrderJob is the daily recurring-payments job. It is schedulable and has two settable properties, processDate (default today) and batchSize (default 50) — see Schedule the daily recurring-payments job.
Mistakes to avoid
| Mistake | What happens | Fix |
|---|---|---|
| Calling the API after DML in the same transaction | Callout exception | Call from an async context, or before any DML |
| Passing card data that came from an untrusted source without validation | Payload rejects it; worse, you may log it | Validate, never log |
Expecting processPayOrder to create the order | It processes an existing Pay Order | Insert the order first |
| Using the deprecated void/refund signatures | An exception | Use the dated signatures |
| Running as a user without the permission set | Access errors | Assign REDA Pay - Admin User to the integration user |
FAQ
Not a REDA Pay one. Expose the global methods through your own Apex REST class if an external system needs them, and protect it accordingly.
Create the records with a data load, then call createPayCustomer and createPayMethod from a batch, one record per execute, within Payload's rate limits.
No. It runs as the current user with the same access checks as the screens.