Status Codes
Payment status codes tell you exactly what happened with each transaction. MoneyHash provides a unified status code system that works the same way across all 50+ payment providers - so you can integrate once and handle payment responses consistently, regardless of which provider processed the transaction.
Instead of learning different error codes for Checkout.com, Stripe, MPGS, Moyasar, and every other provider, you get one standardized system. MoneyHash maps each provider's response to a unified code, while keeping the raw provider data available whenever you need it for debugging or support.
This page explains how to read, understand, and respond to status codes in your integration.
Why Unified Status Codes Matter
When you process payments across multiple providers, each one returns different error codes and messages. For example, one provider might say "insufficient_funds" while another says "not enough balance." Without MoneyHash, you'd need separate logic for each provider.
With MoneyHash's unified codes, you write one integration that works the same way for all providers. A code 7051 (insufficient funds) means the same thing whether it came from Provider A or Provider B. This saves you development time and makes your codebase easier to maintain.
Status Code Ranges
MoneyHash organizes codes into three categories to help you understand payment states:
| Range | Meaning | Examples | What This Means |
|---|---|---|---|
| 6000 | Successful | 6000 | Payment went through. One code because success is definitive. |
| 8000 | Pending | 8000, 8001 | Payment is in progress. Waiting for 3DS verification, provider approval, or customer action. |
| 7000+ | Declined | 7001, 7051, 7387, 7059 | Payment didn't go through. Many codes so you know the specific reason and can respond appropriately. |
When you get a specific decline code like 7051 (insufficient funds) or 7387 (expired card), it replaces the trailing zeros in the general 7000 code range.
How to Read a Status Code in a Webhook
Every transaction webhook includes status information at the operation level. Here's what you'll see:
Example webhook showing status code fields
{
"type": "transaction.purchase.failed",
"intent": {
"id": "94R8B44",
"payment_status": {
"status": "AUTHORIZE_ATTEMPT_FAILED"
}
},
"transaction": {
"id": "61b876ed-9962-4b42-8262-5a30703e68ea",
"operations": [
{
"id": "ovGlQYn",
"type": "purchase",
"status": "failed",
"latest_status": {
"code": "7051",
"value": "failed",
"message": "The account lacks sufficient funds to complete the transaction.",
"localized_message": "The account lacks sufficient funds to complete the transaction.",
"provider_error_code": "INSUFFICIENT_FUNDS",
"provider_error_message": "Not sufficient funds"
}
}
]
}
}Understanding Each Field
code (numeric, like 7051 or 8000)
This is what you'll use to decide what to do next. It tells you the exact status and is consistent across all providers. Use this field in your integration logic - if code is 7051, you know it's insufficient funds regardless of which provider processed it.
value (text, like "pending", "failed", or "successful")
A summary category if you want to quickly filter by general status. For example, many different decline codes will show value: "failed". It's helpful for high-level status displays, but for making decisions about retry logic or user messaging, refer to the code field.
message (English text, system-facing)
MoneyHash's description of what happened, written for your logs and internal debugging. Always in English. Not designed for customer display.
localized_message (customer-facing text)
The message you should show to your customers. Designed to be user-friendly and helpful. When translations are available, this field appears in the customer's language. If you want even better UX, you can create your own message map keyed by code (like: if code 7051, show "Your card doesn't have enough funds").
provider_error_code and provider_error_message (raw provider data)
The exact error code and message from the payment provider (Checkout.com, MPGS, Stripe, etc.). Included so you can debug provider-specific issues or escalate to your support team. This data can contain technical provider details, so don't show it to customers - use localized_message instead.
Understanding Payment Failures: Provider Errors vs MoneyHash Errors
When a payment declines, the decline can come from two sources:
Provider Declines (codes 7000–7699): The payment provider rejected the transaction because of something about the card, account, or transaction itself. MoneyHash captures the provider's error code and message for your reference.
MoneyHash System Errors (codes 7701–7711): MoneyHash generated the error because of a system or connectivity issue - for example, the provider was temporarily unavailable, or there was a validation problem. These codes always start with "MH:" in the message.
You can spot the difference by looking at the message prefix:
MH: The PSP service is unavailable...= MoneyHash error (system issue, likely transient)The account lacks sufficient funds...= Provider error (cardholder issue)
Real Example: How MoneyHash Unifies Provider Errors
Here's an actual webhook showing a soft decline (insufficient funds) - notice how the provider error maps to a MoneyHash unified code:
Full webhook example: Code 7051 (Insufficient Funds)
{
"type": "transaction.purchase.failed",
"intent": {
"id": "94R8B44",
"amount": {
"value": 357.22,
"currency": "AED"
},
"created": "2026-08-15 19:07:49.880389+00:00",
"payment_status": {
"status": "AUTHORIZE_ATTEMPT_FAILED",
"balances": {
"total_voided": "0.00",
"total_captured": "0.00",
"total_refunded": "0.00",
"total_authorized": "0.00",
"available_to_void": "0.00",
"available_to_refund": "0.00",
"available_to_capture": "0.00"
}
}
},
"account": {
"id": "ZGqx7AL"
},
"status_id": "OJ7YkGO",
"api_version": "1.1",
"transaction": {
"id": "61b876ed-9962-4b42-8262-5a30703e68ea",
"type": "payment",
"method": {
"id": "gw0GQPZ",
"display_name": "Provider A - Apple Pay",
"service_provider": {
"id": "gl7p7ML",
"display_name": "Provider A"
},
"processing_service_provider": {
"id": "ZBbOblZ",
"display_name": "Mastercard Payment Gateway Services"
}
},
"status": "purchase.failed",
"created": "2026-08-15 19:07:50.747909+00:00",
"trx_rrn": "622719229465",
"operations": [
{
"id": "ovGlQYn",
"arn": null,
"rrn": "622719229465",
"type": "purchase",
"amount": {
"value": 357.22,
"currency": "AED"
},
"status": "failed",
"statuses": [
{
"id": "l7z8eom",
"code": "8000",
"value": "pending",
"created": "2026-08-15 19:07:50.782487+00:00",
"message": "Pending",
"localized_message": "Pending",
"provider_error_code": null,
"provider_error_message": null
},
{
"id": "OJ7YkGO",
"code": "7051",
"value": "failed",
"created": "2026-08-15 19:07:53.301541+00:00",
"message": "The account lacks sufficient funds to complete the transaction.",
"localized_message": "The account lacks sufficient funds to complete the transaction.",
"provider_error_code": "INSUFFICIENT_FUNDS",
"provider_error_message": "Not sufficient funds"
}
],
"latest_status": {
"id": "OJ7YkGO",
"code": "7051",
"value": "failed",
"message": "The account lacks sufficient funds to complete the transaction.",
"localized_message": "The account lacks sufficient funds to complete the transaction.",
"provider_error_code": "INSUFFICIENT_FUNDS",
"provider_error_message": "Not sufficient funds"
},
"authorization_code": null,
"authorization_status": "FAILED",
"acquirer_transaction_id": "306227688723877"
}
],
"billing_data": {
"email": "[email protected]",
"name": "John Doe"
},
"payment_method_details": {
"type": "APPLE_PAY",
"data": {
"brand": "VISA",
"expiry_year": "2031",
"expiry_month": "12"
}
},
"provider_unique_reference": {
"key": "trx_uuid",
"value": "61b876ed-9962-4b42-8262-5a30703e68ea"
}
},
"operation_id": "ovGlQYn"
}What happened: The payment started normally (code 8000, pending). Then the provider responded that the cardholder didn't have enough funds. The provider's raw error was INSUFFICIENT_FUNDS / "Not sufficient funds". MoneyHash mapped this to the unified code 7051 with the message: "The account lacks sufficient funds to complete the transaction."
Why this matters: Both the MoneyHash message and the provider message say the same thing, but in different words. Because MoneyHash unified it to code 7051, your code handles it the same way regardless of which provider returned the error. If you needed to debug the exact provider response, you have it in provider_error_code and provider_error_message.
What you should do: This is a soft decline. Prompt the customer: "Your card doesn't have enough funds. Please try another card or add funds to your account."
Soft Declines vs Hard Declines
When a payment is declined with a code in the 7000 range, it falls into one of two categories. Understanding which one helps you respond appropriately.
Soft Declines
A soft decline is a temporary issue that might resolve with a retry or a different payment method. Common reasons include:
- Bank declined it this time but might approve on retry (code 7001 - bank decline)
- Cardholder doesn't have enough funds right now (code 7051 - insufficient funds)
- Provider's system is busy (code 7100 - system busy) or timed out (code 7152 - transaction timeout)
- Provider doesn't support this currency or card combination (code 7503 - currency error)
How to respond:
- Prompt the customer to try again or use a different card
- For cards with insufficient funds (7051), suggest adding funds or using a different card
- For transient issues like timeouts (7152), a simple retry often works
- Let the customer choose their next action - don't force retries automatically
Hard Declines
A hard decline is a definitive failure. The same card won't succeed no matter how many times you retry or which provider you try. Common reasons include:
- Card is permanently blocked (code 7004 - card pickup)
- Wrong card details (code 7055 - incorrect credentials)
- Card has expired (code 7387 - expiry date error)
- Transaction flagged for fraud (code 7059 - suspected fraud)
- Cardholder disputed the transaction (code 7018 - customer disputed)
- Too many failed attempts (code 7701 - too many failures)
How to respond:
- Be clear and helpful: "We couldn't process this card. Please try another payment method."
- Optionally, show the specific reason (e.g., "This card has expired" for code 7387)
- Don't offer a retry option - it won't help
- You can close the payment intent since no further attempts will succeed
Payment Status Codes
MoneyHash organizes codes into these ranges:
| Status Code Range | Description |
|---|---|
| 6000 | Payment successful - The payment has been completed and the funds have been captured. |
| 7000 | Payment declined - The payment request was rejected. Check the specific code to understand why and decide your next step. |
| 8000 | Payment pending - The payment is in progress. You'll receive a follow-up webhook when the status changes. |
MoneyHash reserves the right to add more status codes or update existing ones. We'll always give you advance notice so you can adjust your integration if needed.
Soft Decline Codes
| Status Code | Status Message | Description |
|---|---|---|
| 7000 | PSP_FAILED_ERROR | A generic payment processing error occurred. |
| 7001 | PSP_BANK_DECLINE_ERROR | Transaction declined by the bank. |
| 7003 | PSP_INVALID_REQUEST_ERROR | The request contains invalid parameters or is improperly formatted. |
| 7023 | PSP_FEE_ERROR | Declined due to fee rules at the scheme or acquirer level. |
| 7024 | PSP_FILE_ERROR | Issue with stored credentials, token, or account updater data. |
| 7031 | PSP_BANK_NOT_SUPPORTED_ERROR | The payment instrument bank is not supported. |
| 7035 | PSP_ACQUIRER_ERROR | Error originating from the payment acquirer. |
| 7040 | PSP_CONFIGURATION_ERROR | Configuration issue at the payment gateway or provider. |
| 7051 | PSP_INSUFFICIENT_FUNDS_ERROR | The account lacks sufficient funds to complete the transaction. |
| 7061 | PSP_AMOUNT_LIMIT_ERROR | The transaction amount exceeds the allowed limits. |
| 7063 | PSP_SECURITY_ERROR | Security violation or issue during processing. |
| 7092 | PSP_FINANCIAL_NETWORK_UNAVAILABLE_ERROR | Financial network unavailable or unable to route the transaction. |
| 7094 | PSP_DUPLICATION_ERROR | Duplicate transaction or request detected. |
| 7098 | PSP_SHIPPING_ADDRESS_ERROR | The provided shipping address is invalid. |
| 7099 | PSP_SENDER_ERROR | Error related to the transaction sender. |
| 7100 | PSP_SYSTEM_BUSY_ERROR | Unable to process the transaction at this time. |
| 7101 | PSP_RECIPIENT_ERROR | Error with recipient details or account. |
| 7102 | PSP_VALIDATION_ERROR | Validation failed for transaction parameters. |
| 7105 | PSP_LIMIT_EXCEEDED | Some limits were exceeded on the provider side. |
| 7151 | PSP_AUTHENTICATION_FAILED_ERROR | Authentication process for the transaction failed. |
| 7152 | PSP_TRANSACTION_TIMEOUT_ERROR | Processing began but the transaction timed out. |
| 7153 | PSP_MALFUNCTION_ERROR | System or network malfunction during transaction processing. |
| 7154 | PSP_AUTHENTICATION_REQUIRED_ERROR | Authentication is required to complete the transaction. |
| 7503 | PSP_CURRENCY_ERROR | Unsupported or invalid currency specified. |
| 7702 | MH_BILLING_DATA_ERROR | MH: Missing or invalid billing data for the transaction. |
| 7705 | MH_PSP_UNAVAILABLE_ERROR | MH: The PSP service is unavailable at the time of the request. |
| 7707 | MH_PROVIDER_CONNECTION_PARSING_ERROR | MH: Couldn't parse the provider response. |
| 7708 | MH_PROVIDER_CONNECTION_UNKNOWN_ERROR | MH: Unknown error. |
| 7709 | MH_PSP_CONFIGURATION_ERROR | MH: Configuration issue with the PSP connection. |
| 7710 | MH_PROVIDER_ERROR_MAPPING_NOT_SUPPORTED | MH: This provider error mapping is not supported yet, please refer to provider interactions for more details on the error code. |
Hard Decline Codes
| Status Code | Status Message | Description |
|---|---|---|
| 7078 | PSP_PAYMENT_INSTRUMENT_ERROR | The payment instrument provided is invalid or unsupported. |
| 7004 | PSP_CARD_PICKUP_ERROR | Card flagged for pickup due to restrictions or fraud suspicion. |
| 7055 | PSP_PAYMENT_INSTRUMENT_CREDENTIALS_ERROR | Incorrect or missing credentials for the payment instrument. |
| 7013 | PSP_INVALID_AMOUNT_ERROR | The transaction amount is invalid. |
| 7015 | PSP_ISSUER_ERROR | Error originating from the payment issuer. |
| 7017 | PSP_CUSTOMER_CANCELLATION | The transaction was cancelled by the customer. |
| 7018 | PSP_TRANSACTION_DISPUTED_ERROR | Transaction flagged due to a customer dispute. |
| 7057 | PSP_TRANSACTION_NOT_PERMITTED_ERROR | The transaction is not permitted. |
| 7059 | PSP_SUSPECTED_FRAUD_ERROR | Transaction flagged for suspected fraudulent activity. |
| 7103 | PSP_DECLINE_LIST_ERROR | Declined due to being on a block or decline list. |
| 7104 | PSP_RISK_DECLINE_ERROR | Declined due to exceeding risk thresholds. |
| 7387 | PSP_EXPIRY_DATE_ERROR | The card's expiration date is invalid or has expired. |
| 7488 | PSP_TRANSACTION_EXPIRED_ERROR | The transaction has expired. |
| 7500 | PSP_BILLING_DETAILS_ERROR | Invalid or incomplete billing details provided. |
| 7511 | PSP_ACCOUNTS_ERROR | Issues with the accounts related to the payment. |
| 7700 | MH_INTENT_EXPIRED_ERROR | MH: The transaction or intent has expired. |
| 7701 | MH_TOO_MANY_FAILED_TRANSACTIONS_ERROR | MH: A high number of failed transactions were detected within a short period for a single intent, exceeding 20 failures. |
| 7703 | MH_INTENT_CLOSED_ERROR | MH: The intent has already been closed. |
| 7704 | MH_PAYMENT_INSTRUMENT_CREDENTIALS_ERROR | MH: CVV is missing for a Direct API transaction. |
| 7706 | MH_INVALID_REQUEST_ERROR | MH: The request was rejected due to a format or validation error returned by the PSP. |
| 7711 | MH_TRANSACTION_EXPIRED_ERROR | MH: The Transaction has expired. |
Handling Payment Status Codes in Your Integration
Here's how to build status code handling into your integration:
1. Check the code to determine next steps:
The code field is your decision point. It tells you exactly what happened and what you should do.
- If
code == 6000: Payment succeeded. Mark the order as paid and proceed with fulfillment. - If
code == 8xxx: Payment is in progress. Wait for a follow-up webhook (the customer might need to complete 3DS verification, or the provider is processing authorization). - If
code == 7xxx: Payment was declined. Check the soft/hard decline tables above to decide whether to prompt for a retry or suggest a different payment method.
2. For declined payments, respond appropriately:
Use the tables above to see whether the code is a soft or hard decline, then:
For soft declines (like 7001, 7051, 7100, 7152):
- Prompt the customer: "Try again" or "Use a different card"
- Give them options and let them choose
- Consider showing the specific reason ("Your card doesn't have enough funds")
For hard declines (like 7004, 7055, 7387, 7059):
- Be clear and direct: "We couldn't process this card. Please try another payment method."
- Optionally include the specific reason ("This card has expired")
- Don't offer retry options
3. Use the code field for your logic:
The code field (7051, 8000, 6000, etc.) is what you should use in your integration code. The value field ("pending", "failed", "successful") is a summary category that can be helpful for displays, but it's not specific enough for decision-making - always refer to code.
4. For messaging to customers:
- Start with
localized_messagefrom the webhook - it's designed for customer display - Or create your own message map keyed by code for even better UX
- Examples: "Your card doesn't have enough funds. Please try another card" (for 7051), "This card has expired" (for 7387)
- Don't show
provider_error_messageto customers - it may contain technical provider details
5. Handle unknown codes gracefully:
MoneyHash may add new codes in the future. To future-proof your integration, handle codes by their prefix (6xxx, 7xxx, 8xxx) rather than hardcoding every individual code. That way, if a new code is added, your system handles it appropriately by default.
MoneyHash will always notify you in advance when we add or change status codes, giving you time to adjust your integration if needed.
Updated 27 days ago