Skip to main content

Errors

AccruPay uses the standard GraphQL error envelope for all API-level failures. Transaction declines are a separate concern and are not represented as GraphQL errors.


GraphQL error envelope

When an operation fails at the API level, the response includes an errors array and data is null (or the failing field is null).

{
"errors": [
{
"message": "Unauthorized",
"extensions": {
"code": "UNAUTHENTICATED"
}
}
],
"data": null
}

The extensions.code field is the machine-readable error code. Always branch on extensions.code, not on message — message text may change without notice.


extensions.code values

CodeTriggersRecommended action
UNAUTHENTICATEDMissing or invalid accrupay-api-secret headerVerify the API secret is set correctly and is not expired
FORBIDDENValid credentials but insufficient permissions for the requested resourceCheck that the API key belongs to the correct merchant account and has access to the requested operation
NOT_FOUNDThe requested resource (transaction, payment method, plan, etc.) does not exist or does not belong to this merchantVerify the ID is correct and was created under this merchant account
VALIDATION_ERRORRequired field is missing, a value is out of range, or a field fails format validationCheck the message field for field-level detail; fix the input and retry
INTERNAL_SERVER_ERRORUnexpected server-side failureRetry with exponential backoff; if the issue persists, contact AccruPay support with the full error response

Transaction declines are not API errors

warning

A payment that is declined or fails at the provider level does not produce a GraphQL errors entry. The mutation resolves successfully and returns a transaction object. You must check transaction.status in the response data.

{
"data": {
"merchantApiServerPaymentMethodTransactionCreate": {
"id": "txn-uuid",
"status": "DECLINED",
"providerError": "Insufficient funds"
}
}
}

Transaction terminal statuses

StatusMeaningWhat to show the customer
SUCCEEDEDPayment completed successfullyConfirmation — order fulfilled
DECLINEDCard network or issuer declined the chargeAsk the customer to try a different payment method
FAILEDProvider-side processing failure (e.g. timeout, invalid card data)Generic error — try again or contact support
CANCELEDAuthorization was released without captureNo charge was made
SUCCEEDED (action: REFUND)Refund processedConfirm refund amount in refundedAmount field

Check the providerError field for the raw decline reason returned by the provider. This is useful for logging and support, but should not be shown verbatim to customers.


providerError field

Most transaction return types include a providerError field:

{
id
status
providerError
}

providerError is populated when status is DECLINED or FAILED. It contains the provider's raw reason string (e.g. "Do not honor", "Insufficient funds", "Invalid card number").

Use providerError for:

  • Internal logging and alerting
  • Support ticket context
  • Reconciliation when a statement entry is unclear

Do not expose providerError directly to end customers. Map it to a user-friendly message in your application layer.


Network errors vs GraphQL errors

HTTP-level failures (5xx, network timeouts, DNS failures) do not produce a GraphQL errors array — the response body may be empty or non-JSON. Handle these separately:

ScenarioBehaviorRecommendation
HTTP 200 with errors[]GraphQL error — parseable JSONBranch on extensions.code
HTTP 200 with dataSuccessful responseCheck transaction.status for declines
HTTP 401Authentication rejected at the HTTP layer before GraphQLSame as UNAUTHENTICATED — check the API secret
HTTP 5xxServer error before GraphQL processingRetry with backoff
Network timeout / no responseTransport-level failureRetry; use merchantInternalTransactionCode as idempotency key to avoid duplicate charges

Idempotency and retries

merchantInternalTransactionCode is your idempotency key for charge mutations. If a request times out and you are unsure whether it was processed, do not retry with a new code — first query the transaction by merchantInternalTransactionCode to check whether it was created.