Authentication Issues
Invalid or Expired Token
Symptom: 401 Unauthorized response
Causes:
- Access token has expired (tokens are valid for 24 hours)
- Token not included in Authorization header
- Malformed Authorization header
Solutions:
- Request a new access token:
BASH
curl -X POST https://dev-payce.auth.eu-west-1.amazoncognito.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
-d "grant_type=client_credentials"
- Ensure correct header format:
Authorization: Bearer eyJraWQiOiJ...
- Implement token refresh logic before expiry
Invalid Client Credentials
Symptom: invalid_client error from the authentication endpoint
Causes:
- Incorrect client_id or client_secret
- Using sandbox credentials in production or vice versa
- Credentials not Base64 encoded correctly
Solutions:
- Verify credentials match environment (sandbox vs production)
- Check for extra whitespace in credentials
- Ensure Basic auth header is properly formatted:
BASH
# Correct format
-u "client_id:client_secret"
# Or manually encode
echo -n "client_id:client_secret" | base64
Mandate Creation Issues
Bank Account Verification Failure
Symptom: 400 Bad Request with verification failure details
Example Error:
JSON
{
"Message": "Debtor account verification failure: details={\"AccountExists\":true,\"AccountIsOpen\":false,...}"
}
Causes:
- Account is closed or dormant
- Incorrect account number or branch code
- Account type mismatch
- ID number doesn't match the account holder
Solutions:
|Verification Field|Resolution|
|---|---|
|`AccountExists: false`|Verify account number with customer|
|`AccountIsOpen: false`|Customer needs to reactivate or provide different account|
|`AccountTypeMatches: false`|Correct the `accountType` field (CURRENT/SAVINGS/TRANSMISSION)|
|`AccountAcceptsDebits: false`|Account cannot receive debits, use different account|
|`IdNumberMatches: false`|Verify ID number matches primary account holder|
Workaround: Set verifyAccount: false to skip verification (not recommended for production)
Invalid Bank Name Format
Symptom: 400 Bad Request mentioning the bank field
Cause: Bank name not in the correct format
Solution: Use uppercase, single-word format:
|Incorrect|Correct|
|---|---|
|`Standard Bank`|`STANDARDBANK`|
|`Absa`|`ABSA`|
|`First National Bank`|`FNB`|
|`capitec`|`CAPITEC`|
Duplicate External Reference
Symptom: 409 Conflict error
Cause: The externalReference value already exists
Solutions:
- Use unique references for each mandate/collection
- Implement UUID generation:
JSX
const externalReference = crypto.randomUUID();
- Include timestamp or sequence number:
JSX
const externalReference = `MAN-${Date.now()}-${sequenceNumber}`;
DebiCheck Authentication Timeout
Symptom: Mandate status remains PENDING_AUTHENTICATION then becomes AUTH_FAILURE
Causes:
- Customer didn't respond within 120 seconds (TT1)
- The customer's phone is off or has no signal
- The bank couldn't deliver USSD/push notification
Solutions:
- Implement fallback authentication:
JSON
{
"authenticationType": "REALTIME",
"fallbackAuthenticationType": "DELAYED_WITHOUT_AUTH"
}
- Use delayed authentication for after-hours:
JSON
{
"authenticationType": "DELAYED"
}
- Retry with batch processing:
JSON
{
"authenticationType": "BATCH"
}
- Follow up with the customer to ensure they're expecting the authentication request
DebiCheck Mandate Rejected
Symptom: Status AUTH_FAILURE with rejection reason
Causes:
- The customer actively rejected the mandate
- Mandate details don't match customer expectations
- The customer doesn't recognise the merchant
Solutions:
- Verify contract details with the customer before submitting
- Ensure the abbreviated name is recognisable to the customer
- Confirm collection amount and frequency
- Re-submit with corrected details after customer confirmation
Collection Issues
Collection Returned Unpaid
Symptom: Collection status UNPAID
Common Causes and Solutions:
|Reason|Solution|
|---|---|
|Insufficient funds|Wait for next mandated date to retry|
|Account closed|Contact customer for new account details|
|Payment stopped|Contact customer, may need new mandate|
|Not provided for|After 2 consecutive failures, obtain new mandate|
PASA Rules:
- Cannot resubmit until the next mandated date
- After 2 "Not provided for" returns, a new mandate is required
- "Account Closed" or "Payment Stopped" cannot be resubmitted
Collection Disputed
Symptom: Collection status DISPUTED
Causes:
- Customer claims no valid mandate exists
- Collection violates the mandate terms
- The customer cancelled the mandate
Solutions:
- Retrieve and review the original mandate
- Verify collection was within mandate parameters:
- Correct amount (within max limits)
- Correct collection day
- The mandate was active
- Respond to the bank within 30 days with the mandate evidence
- For DebiCheck: Disputes are less likely if the collection matches the authenticated terms
Collection Submitted After Cut-off
Symptom: Collection not processed on the expected date
Cause: Submitted after bank processing cut-off time
Cut-off Times:
|Service|Weekday|Weekend|
|---|---|---|
|Same-day|16:20|09:45|
|One-day|16:00|10:15|
|Two-day|14:30 (2 days prior)|09:00|
|DebiCheck|16:00 (2 days prior)|11:00 (2 days prior)|
Solutions:
- Submit collections well before cut-off times
- Account for your system processing time
- For time-sensitive collections, use same-day service with early submission
Payment Issues
Payment Exceeds Limits
Symptom: Payment rejected with "exceeds industry-imposed limits"
Cause: Payment amount ≥ R5,000,000
Solution: Route high-value payments through a real-time line (contact Precium support)
Payment to an Invalid Account
Symptom: Payment status FAILED
Causes:
- Invalid account number
- Incorrect branch code
- Account doesn't accept credits
Solutions:
- Verify recipient account details
- Consider implementing account verification before payment
- Confirm the branch code matches the account's bank
Webhook Issues
Not Receiving Webhooks
Symptom: No callbacks received at registered URL
Causes:
- Callback URL not registered
- URL not publicly accessible
- HTTPS certificate issues
- Firewall blocking requests
Solutions:
- Verify the callback URL is registered:
BASH
# Register callback URL
curl -X POST https://dev.api.revio.co.za/v2/clientcallbackurl/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"clientId": YOUR_CLIENT_ID,
"url": "https://your-server.com/webhook",
"callbackType": "EFT_COLLECTION",
"callbackVersion": "V2"
}'
- Test with webhook.site first:
JSON
{
"url": "https://webhook.site/your-unique-id"
}
- Ensure your server:
- Is publicly accessible
- Has valid SSL certificate
- Responds within 5 seconds
- Returns HTTP 200
Webhook Timeout Errors
Symptom: Callbacks received but marked as failed
Cause: Webhook handler takes too long to respond
Solution: Return 200 immediately, process asynchronously:
JSX
app.post('/webhook', (req, res) => {
// Respond immediately
res.status(200).send('OK');
// Process in background
processWebhookAsync(req.body);
});
API Request Issues
400 Bad Request
Symptom: Request rejected with validation error
Common Causes:
- Missing required fields
- Check all required fields are present
- Verify field names match API specification (case-sensitive)
- Invalid date format
- Use ISO 8601 format:
2024-01-15T10:00:00.000Z
- Invalid phone number format
- Use format:
+27-XXXXXXXXX
- Invalid amount
- Amount must be in cents (integer)
10000 = R100.00
- Invalid enum values
- Check accepted values for fields like
accountType, serviceType, frequency
404 Not Found
Symptom: Resource not found error
Causes:
- Invalid resource ID
- Resource was deleted
- Wrong endpoint URL
Solutions:
- Verify the ID exists and is correctly formatted (UUID)
- Check endpoint URL matches documentation
- Ensure you're using the correct API version (
/v2/)
500 Internal Server Error
Symptom: Server error response
Actions:
- Note the timestamp and request details
- Check for
x-request-id in response headers - Retry with exponential backoff
- If persistent, contact Precium support with:
- Request endpoint
- Request payload (redact sensitive data)
- Timestamp
- Request ID (if available)
Environment Issues
Using the Wrong Environment
Symptom: Unexpected behaviour, missing data, or authentication failures
Cause: Mixing sandbox and production credentials/endpoints
Environment Reference:
|Environment|Auth Endpoint|API Endpoint|
|---|---|---|
|Sandbox|`dev-payce.auth.eu-west-1.amazoncognito.com`|`dev.api.revio.co.za`|
|Production|`payce.auth.eu-west-1.amazoncognito.com`|(provided at go-live)|
Solution: Use environment variables to manage configuration:
JSX
const config = {
authUrl: process.env.REVIO_AUTH_URL,
apiUrl: process.env.REVIO_API_URL,
clientId: process.env.REVIO_CLIENT_ID,
clientSecret: process.env.REVIO_CLIENT_SECRET
};
Getting Help
If you cannot resolve an issue:
- Check documentation: Review the relevant section of this documentation
- Review Swagger: https://dev.api.revio.co.za/swagger/index.html
- Test in sandbox: Reproduce the issue in the sandbox environment
- Contact support: Email support@precium.com with:
- Description of the issue
- Steps to reproduce
- Request/response examples (redact sensitive data)
- Environment (sandbox/production)
- Timestamp of failed requests