Status codes
Every Syok2Pay response carries a status_code (and, on the HTTP layer, a
matching status). Use the status_code — not the HTTP status alone — to decide
what to do next. Each row below tells you what happened and what to do.
Success
OKThe request was accepted. For PENDING, the final result arrives later via callback or inquiry.
SUCCESSHTTP 200Request completed successfully.
Proceed — read data from the response body.
PENDINGHTTP 200Accepted; awaiting the bank or payment provider.
Wait for the callback, or poll Inquiry. Do not re-initiate.
Validation & parameters
Fix requestThe request was rejected before processing. Fix the request and send it again.
PARAM_MISSINGHTTP 400A required field is missing.
Add the missing field (e.g. amount, currency) and retry.
PARAM_INVALIDHTTP 400A field value is invalid.
Check the format — amount is a 2-dp string, currency is an ISO code.
INVALID_AMOUNTHTTP 400The amount is not a valid positive value.
Send amount as a positive decimal string, e.g. "3.00".
INVALID_CURRENCYHTTP 400The currency is missing or unsupported.
Use a supported currency code such as MYR.
DUPLICATE_REFERENCEHTTP 400This reference_no was already used.
Use a unique reference_no per order. Reusing one is treated as a duplicate.
FUNCTION_NOT_SUPPORTEDHTTP 400The operation isn't available for this product or channel.
Check the product's capabilities or pick a supported payment method.
Authentication
Check credentialsThe request could not be authenticated. These never succeed on retry until the credentials or signature are corrected.
UNAUTHORIZEDHTTP 401Missing or invalid API key.
Send the Authorization header as 'Bearer pk_…'.
INVALID_SIGNATUREHTTP 401The X-Signature did not match.
Rebuild the signing string, sign with your secret key, and check X-Timestamp is fresh.
INVALID_API_KEYHTTP 401The API key is not recognised.
Verify the key and that your merchant account is active.
EXPIRED_API_KEYHTTP 401The API key has expired.
Generate a new key in the merchant dashboard.
FORBIDDENHTTP 403Authenticated, but not allowed to access this resource.
Ensure merchant_code matches your account and you own the transaction.
IP_NOT_ALLOWEDHTTP 403Your server IP is not whitelisted.
Add the calling IP to your merchant IP allowlist.
MERCHANT_INACTIVEHTTP 403The merchant account is inactive or suspended.
Contact support to reactivate the account.
Not found
Not foundThe referenced resource does not exist (or is no longer retrievable).
SESSION_NOT_FOUNDHTTP 404No session matches that session_id.
Check the session_id; create a new session if it has been purged.
TRANSACTION_NOT_FOUNDHTTP 404No transaction matches that id.
Verify the txn_id, or look it up via Inquiry using your reference_no.
INVALID_MERCHANTHTTP 400The merchant_code is unknown.
Confirm the merchant_code is correct and registered.
INVALID_PRODUCTHTTP 400The product_code is unknown or not linked to you.
Use a valid product_code that is enabled for your account.
Session & transaction state
Check stateThe resource exists but its current state does not allow this operation. Check the state first, then act.
SESSION_EXPIREDHTTP 400The session passed its expiry time.
Create a new session — sessions are short-lived.
SESSION_COMPLETEDHTTP 400The session is already paid.
Do not reuse it; start a new session for a new payment.
SESSION_CANCELLEDHTTP 400The session was cancelled.
Create a new session if the customer wants to retry.
VOID_NOT_ALLOWEDHTTP 400This transaction can't be voided in its current state.
Only authorised or pending transactions can be voided.
REFUND_NOT_ALLOWEDHTTP 400This transaction can't be refunded in its current state.
Only captured transactions can be refunded.
Payment declined
Customer actionThe payment was attempted but not completed. The customer usually needs to take action.
PAYMENT_FAILEDHTTP 400Payment processing failed.
Let the customer retry; create a new session if needed.
PAYMENT_DECLINEDHTTP 400The bank or provider declined the payment.
Ask the customer to try another card, bank, or method.
PAYMENT_CANCELLEDHTTP 400The customer cancelled at the payment page.
Offer a new session to try again.
Server & transient
RetrySomething went wrong on our side, or a dependency was briefly unavailable. These are safe to retry idempotently with the same reference_no.
INTERNAL_ERRORHTTP 500Unexpected server error.
Retry with backoff; if it persists, contact support with the trace_id.
BACKEND_UNAVAILABLEHTTP 503The payment processor is unreachable.
Retry after 30–60s; check the status page.
TIMEOUTHTTP 504The backend did not respond in time.
Retry idempotently using the same reference_no.
Retrying safely
Always retry with the same reference_no. Initiate is idempotent on
reference_no, so a retried request returns the original session instead of
creating a duplicate charge. Only Server & transient errors should be
retried automatically — use exponential backoff (1s, 2s, 4s…).
Every error response also includes a trace_id. Include it when contacting
support so we can find the exact request in our logs.