JavaScript is required to view this page
Troubleshooting

Troubleshooting

This guide covers common issues you may encounter when integrating BlinkPay, along with solutions and debugging strategies.

Common Errors

HTTP Error Codes

Error CodeMeaningCommon CausesActions
400Bad RequestInvalid request format, missing required fields, invalid date formats, redirect URI not whitelistedCheck request format, verify all required fields, ensure dates are ISO 8601 with timezone
401UnauthorisedInvalid or expired access tokenRefresh OAuth token automatically and retry request
403ForbiddenBlink Payments: feature not enabled or wrong subscription tier. Blink Data: the consent's state or permissions (BDT409–BDT415), or a flow the bank doesn't offer (BDT401, BDT402)Blink Payments: verify feature access with support. Blink Data: read the code — see 403 Forbidden
404Not FoundInvalid consent ID, payment ID, or resource IDVerify IDs are correct, check consent/payment hasn't expired
409ConflictDuplicate request, resource conflictDepends on the code: some mean retry, others poll — see When to Retry
415Unsupported Media TypeInvalid payload format or missing Content-Type headerEnsure payload is valid JSON and Content-Type is application/json
422Unprocessable ContentBlink Payments: consent expired/revoked, invalid consent state, amount exceeds limits. Blink Data: see the Blink Data error codes pageCreate new consent, verify consent status; Blink Payments: check enduring consent limits
429Too Many RequestsToo many requests in a short timeWait for the Retry-After time, then back off — see API Rate Limits
5xxServer ErrorBlinkPay or bank system issueRetry the request (with the same idempotency-key for a POST), contact support if persistent

Authentication Issues

401 Unauthorised

Symptom: All API requests return 401

Causes:

  • Access token expired (lifetime: 1 hour)
  • Invalid client credentials
  • Environment mismatch (sandbox credentials in production)

Solutions:

  1. Implement automatic token refresh - cache token with expiry, refresh 5 minutes before expiration
  2. On 401 response: request new token and retry the original request
  3. Verify credentials match your environment (sandbox vs production)

403 Forbidden

Symptom: Specific endpoints return 403

On both products, a 403 can mean your access token lacks the scope the endpoint needs. Scopes are assigned to your API client by BlinkPay; contact support if one is missing.

Blink Payments: the feature is not enabled for your account, or your subscription tier doesn't include it. Contact support to verify feature access and your subscription.

Blink Data: read the code in the response body; the consent is rejected, revoked, expired, not yet authorised, or lacks the permission the endpoint needs. Create a new consent, or wait for authorisation. The Blink Data error codes page lists them.

Symptom: Consent doesn't progress after redirect

Causes:

  1. Customer didn't complete authorisation
  2. Customer closed the bank app or browser without finishing
  3. Bank system issue
  4. Network timeout

Solutions:

  1. Once the customer has returned (or the decoupled callback has fired), poll the consent every second until it leaves AwaitingAuthorisation; in the direct decoupled flow with no callback, every 5 seconds
  2. Check for terminal states: a consent waiting at the bank ends as either Authorised or Rejected
  3. Display appropriate UI to customer while waiting

What happens if the customer closes the bank app or browser before finishing? The consent stays AwaitingAuthorisation until the bank's window ends and then becomes Rejected; no money moves and no data is shared. If the customer comes back to your site or app without finishing, don't revoke the consent or treat it as failed: they may still approve it in their banking app. Keep checking until the window ends, then reconcile.

Prevention:

  • Clearly explain the process to customers
  • Minimise steps before redirect
  • Provide clear instructions
  • Consider decoupled flow for known customers

Symptom: The consent reaches a terminal status before the customer authorises it — Rejected if they'd already reached their bank, or GatewayTimeout if they never chose one

Cause: Authorisation windows are set per bank and per flow, and gateway consents have an earlier session cutoff before bank selection. Blink Payments: read the applicable window from redirect_flow.request_timeout and features.decoupled_flow.request_timeout on the metadata endpoint rather than hard-coding a figure. Blink Data: GET /v1/meta has no timeouts; use the per-bank windows instead: 15 minutes for bank selection in the gateway, up to 10 minutes for the redirect flow, and a few minutes for the decoupled flow, varying by bank.

Handling:

  • Display user-friendly message: "Your session expired. Please try again."
  • Offer retry option that creates a new consent
  • Log the timeout for monitoring

Prevention:

  • Streamline checkout flow
  • Explain process upfront
  • Set customer expectations
  • Consider decoupled flow for complex cases

Symptom: Consent status becomes 'Rejected'

Common Causes:

  • Customer clicked "Cancel" or "Decline"
  • Customer failed authentication multiple times
  • Account doesn't support requested operation
  • Insufficient funds (for payment consents)
  • Bank fraud detection triggered

Handling:

  • Display a clear error message. The API has no rejection-reason field; on a redirect or gateway return, the status parameter gives the kind of outcome and error carries text you can show (see Return Parameters)
  • Suggest: check account balance, use different account, contact bank
  • Offer retry option or alternative payment method

Important: Never automatically retry rejected consents. Customer needs to resolve the underlying issue first.

Blink Payments only: for quick payments, a rejected consent also appears as a payment record with status Rejected in the consent's payments[] array.

Payment Issues

Blink Payments only.

Payment Stuck in Pending

Symptom: Payment doesn't move to AcceptedSettlementInProcess

Expected Timeline: Most payments move within seconds. Poll every second until the payment reaches AcceptedSettlementCompleted or Rejected; if it hasn't within a minute or two, stop and pick it up in your periodic wash-up.

If still Pending after 6 hours:

  1. Log the issue with payment ID and age
  2. Contact BlinkPay support with the consent ID, payment ID and request ID
  3. Monitor for status change

Payment Rejected

Symptom: Payment status becomes 'Rejected'

Common Causes:

ReasonDescriptionAction
Insufficient FundsAccount balance too lowAsk customer to add funds or use different account
Account ClosedAccount no longer activeUse different account
Invalid AccountAccount number incorrectVerify account details
Payment BlockedBank fraud detection or customer blockContact bank, verify legitimacy
Exceeds LimitsDaily/transaction limit exceededSplit payment or wait for limit reset
Technical ErrorBank system issueRetry or contact support

Handling:

  • Log the rejection for analysis
  • Display a user-friendly message. The payment carries no rejection reason, so suggest the customer checks with their bank
  • Offer retry or alternative payment method. A new attempt needs a new idempotency-key

Integration Issues

Redirect URI Not Working

Symptom: Customer not redirected back after authorisation

How a redirect URI is matched against your registered entries:

PartRule
Scheme, host and portMust match exactly (the host is not case-sensitive)
PathPrefix match: registering /callback also accepts /callback/success, and /callbackfoo, so register a path that ends in a distinct segment
Trailing slashA registered trailing slash is required: registering /callback/ rejects /callback. Register /callback, not /callback/
Query stringIgnored, so you can append your own parameters (e.g. ?order=123)
Wildcardhttps://*.example.com matches any subdomain but not the bare https://example.com
EnvironmentProduction rejects http:// and localhost; sandbox allows them. Custom app schemes (e.g. myapp://callback) are allowed in both

A URI that matches no entry is rejected with 400 (Blink Payments BP214, Blink Data BDT211). The decoupled flow's callback_url is not checked against this list.

Common Mistakes:

  • Protocol mismatch: http:// vs https://
  • Registering /callback/ and sending /callback
  • Subdomain differences: yourapp.com vs www.yourapp.com — consider using a wildcard entry like https://*.yourapp.com/callback
  • Port number mismatch
  • Registering in sandbox but calling production (each environment has its own list)

Debugging:

  • Log callback requests to see the full URL received
  • Check for the cid query parameter, which carries the consent ID (see Return Parameters)
  • Verify the callback URL in browser network tools

CORS Errors

Symptom: Browser console shows CORS errors

Root Cause: BlinkPay API calls must be made from your backend server, not browser JavaScript

Solution:

  1. Frontend calls your backend API
  2. Backend calls BlinkPay API
  3. Backend returns result to frontend

Never expose your client credentials or make BlinkPay API calls directly from browser code.

Mobile Deep Linking Issues

Symptom: Banking app doesn't open or return navigation fails

Solutions:

PlatformNot supportedUse
iOSEmbedded WKWebViewSFSafariViewController or ASWebAuthenticationSession
AndroidEmbedded WebViewChrome Custom Tabs

Embedded WebViews are not supported: many banks block their pages from being embedded, and a real browser keeps the customer's bank credentials out of your app and shows them the bank's real address.

Debugging:

  • Add logging to your deep link handler
  • Verify URL scheme, host, and query parameters
  • Test on actual devices (not simulators)

See Mobile Integration Guide for complete details.

Validation Errors (400)

Common Validation Issues

Invalid date format:

  • Blink Payments: wrong "from_timestamp": "2025-01-01"; correct "from_timestamp": "2025-01-01T00:00:00+13:00" (ISO 8601 with timezone)
  • Blink Data: the consent dates (expiration_date_time, start_date_time, end_date_time) and the data filters (from_booking_date_time, to_booking_date_time, from_statement_date_time, to_statement_date_time) need a full date-time with an offset, such as 2026-12-31T23:59:59+13:00; a date alone is rejected. In a query string a raw + decodes to a space, so use Z (2026-09-01T00:00:00Z) or encode it as %2B13:00. A consent's expiration_date_time must not fall on the day you create it (BDT258), and a data filter must fall within the consent's start_date_time to end_date_time window (BDT236)

Amount format (Blink Payments):

  • A string with a decimal point and one or two decimal places, greater than zero, in NZD: "100.00" or "100.5", not "100". Send two decimal places

PCR fields (Blink Payments):

  • particulars is required (1-12 characters); code and reference are optional (up to 12 characters each)
  • Allowed characters: letters, digits, space and - & # ? : _ / , . '. Anything else is rejected, not stripped
  • Example: "particulars": "INV12345", "code": "SALE", "reference": "CUST001"

Invalid bank:

  • Both products take the same case-sensitive bank values: ANZ, ASB, BNZ, Kiwibank, NZHL, Westpac, and PNZ in the sandbox
  • Blink Data: a value the API doesn't recognise returns 400 BDT243. A bank your organisation isn't set up for returns 400 BDT213; in the sandbox, use PNZ. A flow the bank doesn't offer returns 403 BDT401 (redirect) or BDT402 (decoupled)

Redirect URI not whitelisted:

  • Error: "Redirect URI not whitelisted"
  • Solution: Register the URI in the client portal under Settings > API Settings, for the environment you're calling (sandbox, production). You can add an exact URI or a wildcard subdomain entry (e.g., https://*.example.com/callback) to match multiple subdomains. This requires the Developer or Administrator role — otherwise email support@blinkpay.co.nz with the URI(s) you need registered.

Retry Logic

When to Retry

Error TypeRetry?Notes
5xx Server Error✅ YesRetry with exponential backoff, with the same idempotency-key for a POST
429 Rate Limited✅ YesWait at least the Retry-After time, then back off exponentially — see API Rate Limits
401 Unauthorised✅ YesAfter getting a new access token
409 BP708, BP711 (Blink Payments)✅ YesRetry the same request with the same key; the earlier request is still in progress
409 BP715 (Blink Payments)✅ YesRetry the refund with a new idempotency-key
409 BP703 (Blink Payments)❌ No, pollPoll the payment named in the message instead of resubmitting
409 BP712 (Blink Payments)⚠️ Check firstRead the consent's payments before retrying; the other request may already have succeeded
409 BDT704 (Blink Data)✅ YesRetry the consent creation with the same key once the earlier request has completed
4xx or 5xx on the first quick-payment GET (Blink Payments)✅ YesRetry the GET: the outcome is not yet known, so don't treat the payment as failed
Other 4xx Client Errors❌ NoFix the request - these indicate request problems

Retry Strategy

For 5xx errors, use exponential backoff:

  • Max retries: 2
  • Initial delay: 0.5 seconds
  • Multiplier: 2x (delays: 0.5s, 1s)

A couple of quick retries rides out a brief network or service blip without keeping your customer waiting. If the request still fails, stop and check the state of the consent or payment later rather than retrying in a loop. Always use idempotency keys when retrying POST requests to prevent duplicates.

Idempotency Keys

Idempotency keys prevent duplicate operations when retrying requests. Send the key in the idempotency-key header. The two products apply it differently.

Blink Payments:

ScenarioResult
Same key + same payload, within 24 hoursOriginal response returned (safe to retry)
Same key + different payload409 Conflict error (BP702)
Same key, earlier request still in flight409 Conflict error (BP708), or BP703 naming the in-flight payment — poll it
Same key, earlier payment terminal, replay window expired409 Conflict error (BP710) naming that payment and its status; use a fresh key
Same key after the payment ended RejectedThe rejected payment is returned again (or BP710), so nothing is retried; use a fresh key

When to reuse a key: reuse the same key only when you don't know whether the request succeeded (a timeout, a network error or a 5xx). For a new attempt after a payment is Rejected, use a new key.

Best practices (Blink Payments):

  • Use a unique UUID per distinct request (Blink Payments rejects a key that is not a UUID with 400)
  • Keys are cached for 24 hours, but the binding to the payment they created is permanent
  • Always include when retrying payment creation requests
  • Gateway-flow consents are de-duplicated on the request-id header rather than idempotency-key, so resend the same request-id when retrying one

Blink Data: only POST /v1/consents takes an idempotency key. Send a UUID; BlinkPay remembers it for 24 hours for your organisation. Without a key there is no protection, and a retried request can create a second consent.

ScenarioResult
Same key + same body, within 24 hours201 with the original consent_id and redirect_uri; no second consent
Same key + different body409 Conflict error (BDT701)
Same key, earlier request still in progress409 Conflict error (BDT704); retry once it completes

Bank Maintenance

Banks may have scheduled maintenance windows, typically overnight (NZ time).

How Maintenance Affects Payments

Blink Payments:

Flow TypeBehaviour During Maintenance
GatewayAffected bank is hidden from bank selection
In-progress paymentsAcceptedSettlementInProcess payments complete after maintenance ends

Handling Maintenance

  • Don't automatically retry payments that are AcceptedSettlementInProcess
  • Don't treat a payment as successful until it reaches AcceptedSettlementCompleted
  • Do allow additional time for overnight payments to settle before treating as failed

Blink Data: a bank that is unavailable, including during maintenance, returns 503 BDT601 on consent creation and data requests. Retry with exponential backoff, and if it persists, try again later.

Debugging Techniques

Request Headers for Debugging

Include these headers with your API requests to enable better tracing and debugging. Send request-id, x-correlation-id and idempotency-key as UUIDs: Blink Payments rejects any other value with 400.

HeaderPurposeExample
request-idUnique identifier for each request. Generate a UUID. Include when contacting support.request-id: 550e8400-e29b-41d4-a716-446655440000
x-correlation-idTrack multiple related requests in a session. Useful for debugging multi-step flows.x-correlation-id: 9b2f6c1e-4d7a-4e8b-a0c3-2f5d8e1b7a64
idempotency-keyPrevent duplicate payments (Blink Payments) or consents (Blink Data, POST /v1/consents only). Generate a UUID per request and reuse it when you retry that request.idempotency-key: 3f1c9a2e-7b4d-4c6e-9a8f-1d2e3b4c5a6f
x-customer-ipCustomer's IP address. Helps with fraud detection and debugging.x-customer-ip: 203.0.113.42

Request ID for Support

When contacting BlinkPay support, include the request-id from your API calls. This allows BlinkPay to quickly locate your request in their logs.

Logging Best Practices

For debugging and audit purposes:

  • Log all API request/response pairs (sanitise sensitive data)
  • Record the request-id returned in response headers
  • Track request duration for performance monitoring
  • Never log full access tokens or client secrets

Getting Support

If issues persist after troubleshooting, contact support@blinkpay.co.nz with your environment, consent/payment IDs, and steps to reproduce.

View full support resources →

Service Status

Check system status: www.blinkpay.co.nz/service-status

Sign up for updates on that page to be notified of any incidents.