Work in progressThis section is currently under active development as part of improvements planned for 2026. Content may change as we expand product capabilities.If you’re interested in early access or want to learn more about what’s coming, feel free to reach out to the team.
This guide walks through the complete flow to generate a PAD (Pre-Authorized Debit) signing link using the EFT API, starting from a contact ID. The PAD link is a URL you present to your end user so they can authorize the payment.
Prerequisites
- A valid
x-client-id API key
- A stored contact with at least one EFT bank account
Overview
The flow requires five API calls in sequence:
| Step | Endpoint | Returns |
|---|
| 1 | GET /api/v1/contacts/{contactId} | Contact details + bank account IDs |
| 2 | GET /api/v1/purposecategories/{direction} | Valid purpose codes |
| 3 | POST /api/v1/transactions | Schedule with id |
| 4 | GET /api/v1/schedules/{scheduleId} | Schedule details with padId |
| 5 | GET /api/v1/pads/{padId} | PAD details with padLink |
Retrieve the contact to obtain their EFT bank account ID.
curl 'https://payments.flinksapp.com/api/v1/contacts/{{contactId}}' \
--header 'x-client-id: {{your-client-id}}'
From the response, note the id from the contact’s EFT account — you’ll use it as the accountId in the transaction request.
Step 2: Get Purpose Categories
Fetch the available purpose categories for DEBIT transactions.
curl 'https://payments.flinksapp.com/api/v1/purposecategories/Debit' \
--header 'x-client-id: {{your-client-id}}'
Each category contains purposeCodes — pick the one that matches your use case and note its value. This becomes the transactionCode in the next step.
Step 3: Create the Transaction
Create a DEBIT transaction using the contact’s contactId and accountId from Step 1, and the transactionCode from Step 2.
curl 'https://payments.flinksapp.com/api/v1/transactions' \
--header 'Content-Type: application/json' \
--header 'x-client-id: {{your-client-id}}' \
--data '[{
"transactionCode": 450,
"amount": 250.00,
"paymentDirection": "DEBIT",
"currency": "CAD",
"payor": {
"accountInfo": {
"accountId": "{{accountId}}"
},
"contactInfo": {
"contactId": "{{contactId}}"
}
},
"scheduleInfo": {
"paymentFrequency": "Monthly",
"startDate": "2026-05-01",
"transactionsCount": 12
}
}]'
The response contains a schedules array. Note the id (schedule ID) from the first item.
The padId field in the create transaction response is null at this point. The PAD agreement is generated asynchronously — you need to poll the schedule to obtain it.
Step 4: Get the Schedule (poll for padId)
Retrieve the schedule to check if the PAD has been generated.
curl 'https://payments.flinksapp.com/api/v1/schedules/{{scheduleId}}' \
--header 'x-client-id: {{your-client-id}}'
Check the padId field in the response:
- If
padId is not null — proceed to Step 5
- If
padId is null — the PAD is still being generated; wait and retry
We recommend polling every 2–3 seconds for up to 30 seconds. If padId is still null after that, contact Flinks support.
Step 5: Get the PAD Link
Once you have the padId, retrieve the PAD agreement details including the signing link.
curl 'https://payments.flinksapp.com/api/v1/pads/{{padId}}' \
--header 'x-client-id: {{your-client-id}}'
The response includes a padLink field — this is the URL you present to your end user.
Presenting the PAD to the End User
Redirect or display the padLink to your end user so they can review and sign the PAD agreement. Once signed, the payment schedule becomes active.
// Example: redirect user to the PAD signing page
window.location.href = padLink;
Complete Example
const BASE_URL = 'https://payments.flinksapp.com/api/v1';
const headers = {
'Content-Type': 'application/json',
'x-client-id': 'your-client-id'
};
async function generatePadLink(contactId) {
// Step 1: Get contact details
const contact = await fetch(`${BASE_URL}/contacts/${contactId}`, { headers })
.then(r => r.json());
const accountId = contact.accounts.eftAccounts[0].id;
// Step 2: Get purpose categories
const categories = await fetch(`${BASE_URL}/purposecategories/Debit`, { headers })
.then(r => r.json());
const transactionCode = categories[0].purposeCodes[0].value;
// Step 3: Create transaction
const txResponse = await fetch(`${BASE_URL}/transactions`, {
method: 'POST',
headers,
body: JSON.stringify([{
transactionCode,
amount: 250.00,
paymentDirection: 'DEBIT',
currency: 'CAD',
payor: {
accountInfo: { accountId },
contactInfo: { contactId }
},
scheduleInfo: {
paymentFrequency: 'Monthly',
startDate: '2026-05-01',
transactionsCount: 12
}
}])
}).then(r => r.json());
const scheduleId = txResponse.schedules[0].id;
// Step 4: Poll schedule for padId
let padId = null;
for (let i = 0; i < 10; i++) {
const schedule = await fetch(`${BASE_URL}/schedules/${scheduleId}`, { headers })
.then(r => r.json());
if (schedule.padId) {
padId = schedule.padId;
break;
}
await new Promise(resolve => setTimeout(resolve, 3000));
}
if (!padId) throw new Error('PAD not generated within timeout');
// Step 5: Get PAD link
const pad = await fetch(`${BASE_URL}/pads/${padId}`, { headers })
.then(r => r.json());
return pad.padLink;
}
API Reference