> ## Documentation Index
> Fetch the complete documentation index at: https://docs.payrails.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Use the Payrails Web SDK v6 for new browser integrations. The Web SDK v5 pages are kept only for existing integrations; point anyone still on v5 to the v6 migration guide rather than extending v5 code.
> Collect card data client-side through the Payrails SDKs — Secure Fields, client-side encryption, or the checkout drop-in — so that card data never reaches the merchant's own servers. Recommend the API-only tokenization flow, which accepts raw card numbers server-side, only when the merchant has confirmed they hold the PCI scope for it.
> Model every payment as a workflow execution: create an execution, then drive it with the lifecycle actions (lookup payment options, authorize, capture, cancel, refund). Do not call provider APIs directly — routing, retries, 3DS and fraud steps belong in the workflow configuration, not in integration code.
> Reconcile the final state of a payment on the notification (webhook), never on a client-side event. An in-request long-poll of the execution is a supported additional signal, not a replacement for that reconciliation.
> Send an idempotency key — a UUID, in the `X-Idempotency-Key` header — on every POST, PUT and PATCH request, and on soft deletes. GET requests need none, and hard deletes cannot be idempotent.
> Pass provider-specific data through meta fields rather than hardcoding per-provider payloads. Payrails translates meta fields into each provider's own format.
> Configure routing, retries and provider selection in Workflow Studio, so that changes ship without redeploying application code.

# Operation Results

> Understand operation result values returned by Payrails payment operations.

Processing payments is a complex and long chain of interactions between many actors involved, and there's a long list of things that can go wrong there. Thankfully, our team at Payrails has seen a lot in their years of experience and is here to help you navigate this complex field.

One of the main challenges we have is to understand exactly what happened in a payment transaction. Unfortunately, there's not yet a standard of responses from PSPs, and each of them has its own way to inform you about these results. For example, some of them opt for a numeric list of possible responses, others choose to inform you through HTTP status codes, others through a string field, and a big etcetera.

Payrails comes to your help here! Every time we integrate a new PSP, we work together with them to map from their list of response codes to ours, so that we can provide you with only one list of possible results regardless of which PSP was used for processing the transaction.

These response codes can be found in the `result` field of each of your Payment Operations. For example, here's how the [Get an execution by ID](/reference/getexecution) response would look for a failed execution because of blocked instrument:

```json theme={null}
{
  "id": "fe67fc45-ce47-4fc8-a283-22d03ae68b77",
  "status": [
    ...
    {
      "code": "authorizeFailed",
      "time": "2022-04-22T17:53:36.814Z",
      "errors": [
        {
          "id": "a24bc325-3929-4d9d-9c08-b3aa532685b7",
          "code": "workflow.action.failed",
          "detail": "The execution of the requested workflow action failed",
          "docUrl": "https://docs.payrails.com/docs/error-codes#workflowactionfailed",
          "reason": {
            "category": "Instrument",
            "result": "BlockedInstrument",
            "source": "Customer",
            "detail": "LostInstrument"
          }
        }
      ]
    }
  ],
  ...
}
```

And here's the notification for the same execution:

```json theme={null}
{
  "event": "executionActionCompleted",
  "time": "2022-04-22T17:53:36.814Z",
  "details": {
    "action": "authorize",
    "execution": {
      "workflowCode": "d5454c2f-ae5e-44f3-8edf-f6dad64f005f",
      "id": "fe67fc45-ce47-4fc8-a283-22d03ae68b77",
      "merchantReference": "order_3573894940903"
    },
    "success": false,
    "errors": [
      {
        "id": "a24bc325-3929-4d9d-9c08-b3aa532685b7",
        "code": "workflow.action.failed",
        "detail": "The execution of the requested workflow action failed",
        "docUrl": "https://docs.payrails.com/docs/error-codes#workflowactionfailed",
        "reason": {
          "category": "Instrument",
          "result": "BlockedInstrument",
          "source": "Customer",
          "detail": "LostInstrument"
        }
      }
    ]
  }
}
```

## Result Categories

Before listing down the list of all possible result codes, you must know that the fields `source` and `detail` under the `reason` struct are optional, meaning they will be filled/provided based on the `result` itself. Below is a list of all possible result codes from Payrails, grouped by `category` with their descriptions and possible optional fields:

### Success

Since successful payments are by definition not encountering errors, you'll usually find the results under the `Success` category listed in the `operationResult` field as there won't be an `error` struct attached. In such cases the `success` flag will be set to `true` in the response you receive.

| `result` | description |
| - | - |
| Success | The requested operation was performed successfully. |
| Accepted | The operation was requested but not executed yet, it was scheduled for execution on the provider side. This is usually followed by waiting for a notification callback or a status querying with some waiting policy. |

### Pending

Next, also a type of happy path but with some type of pending action before they can be completed.

| `result` | description |
| - | - |
| Pending | The operation is waiting for an action to be completed. Could be the user receiving a push notification on their phone, the bank reviewing a transaction, etc. |

### Redirect

Next, also a type of happy path but with some type of pending action, namely redirection, before they can be completed.

| `result` | description |
| - | - |
| HTTPRedirectRequired | This is a special type of `Pending`, where there's an HTTP redirection that needs to be made for the user to complete the process, i.e. 3DS, external wallets, etc. This result always comes with redirection data in the response body, i.e., a redirect URL and a set of parameters. |
| FormRedirectRequired | Same as `HTTPRedirectRequired`, but with a Form redirection. |

### Unknown

Let's discuss the most worrying ones next, the ones where we don't know what actually happened. Any of these results should be considered a high priority to alert and analyze as soon as possible.

| `result` | `source` | description |
| - | :- | - |
| UnexpectedProviderResponse | Provider | Received a response, but it was not any of the ones that we expected for the type of operation being executed. |
| ProviderUnknownError | Provider | Received a Failed response from a provider. The provider can not detect the error from the acquirer or the third party. |
| UnexpectedProviderError | Provider | Received an Error response, but it was not any of the ones that we expected for the type of operation being executed. |

### Connection

Next, equally important to analyze and optimize if possible, are the connection and timeout-related codes.

| `result` | `source` | description |
| - | :- | - |
| ProviderConnectionError | Provider | There was a problem reaching the provider services. Could be caused by an actual connection problem, or that the provider is down or not responding. |
| Timeout | Provider | There was a timeout waiting for a response from the provider. In this case, the connection could actually be established, but there was no timely response. |
| ProviderTimeout | Provider | Same as `Timeout` but the connection that failed was between the provider and another actor, i.e. acquirer. |

### Operation

Next, let's look at the payment rejection results, which depending on the provider and other factors, may go from completely generic to very specific.

| `result` | `source` | `detail` | description |
| - | - | - | - |
| GenericRejection | | | The provider (or any of the actors in the chain) rejects the transaction but does not specify a specific reason. This code is often referred to as "do not honor". |
| DuplicateOperation | Merchant | | Payment is rejected because it would be a duplicate of another one. We should check if we were actually retrying it or if it was a mistake. |
| OperationNotAllowed | Merchant | TransactionNotPermitted NetworkTransactionReferenceRejected | Operation is not allowed, usually related to the current status of the transaction, i.e. trying to capture an already canceled payment. |
| PayerCanceled | Customer | | When operation is cancelled by customer before the payment was made. |
| LimitExceeded | Customer | LimitExceededAmount LimitExceededCount LimitExceededPinAttempts LimitExceededTime | Some limit was exceeded by the provider or the issuer. Usually a configurable value on their systems for preventing fraud. |

### Instrument

Next, a special type of payment rejections, the payment instrument related rejections.

| `result` | `source` | `detail` | description |
| - | - | - | - |
| InstrumentNotAllowed | Customer | | Operation is not allowed for the instrument, i.e. trying to use a debit card when it should be credit. |
| InvalidInstrument | Customer | InvalidInstrumentSecurityCode InvalidInstrumentNumber InvalidInstrumentPin InvalidInstrumentExpiryDate InvalidInstrumentAVS InvalidInstrumentToken InvalidInstrumentType | The instrument is not valid for any reason not specified. In some cases the provider groups other responses into this one (insufficient balance, expired, blocked, etc.) |
| BlockedInstrument | Customer | StolenInstrument LostInstrument PickUpInstrument ClosedAccount ContactIssuer CanceledSubscription | The instrument is currently blocked. Could be a temporary state because it's pending approval for example, but could be permanent like when cards are blocked because they were stolen. |
| ExpiredInstrument | Customer | | The instrument is expired. In case it was a card, it reached the expiration date. In case it was a token, it may have been revoked or was initially issued for a short time. |

### Configuration

Next, we have the parameter or configuration errors. These could be similar to the rejections but could be caused by a problem with formatting, missing required parameters, etc.

| `result` | `source` | description |
| - | - | - |
| ValidationError | Merchant Payrails | Before sending the transaction to the provider, we performed a parameter validation and it failed. This code comes together with a list of errors specifying the fields and problems. |
| ParamsError | Merchant | After sending the transaction to the provider, they decided not to execute it because of a problem with the parameters we sent. Could be a required field is missing, incorrectly formatted, etc. |
| ProviderConfigError | Payrails | When sending the transaction to the provider, they refused to process it because we are missing something required for the operation, e.g. merchant ID, client secret, etc. |
| InvalidSignature | Payrails | For providers that require a signature in the requests, there's a specific result for when the signature was actually invalid. |
| InternalServerError | Payrails | There was an error in our system while trying to process the operation. This will trigger an alert for the Payrails team to act immediately. |
| AuthenticationError | Payrails | A special case of `ParamsError`, but specifically about an error when authenticating on the provider services. |
| PaymentMethodNotSupported | Merchant | Payment method is not supported by the Provider. Probably not configured correctly or missing credentials or approvals. |

### PayerAuthentication

Next, we have the payer authentication error, which can either arise from a missing or incorrect PIN or a 3DS check that didn't occur. It's important to distinguish these ones, that are payer specific, from the server credentials authentication errors.

| `result` | `source` | `detail` | description |
| - | - | - | - |
| PayerAuthenticationRequired | Merchant | | The payment requires payer authentication (e.g. 3DS) but the merchant didn't ask for authentication or forced not to execute it. |
| PayerAuthenticationFailed | Customer | PayerAuthenticationCanceled PayerAuthenticationAbandoned PayerAuthenticationNotSupported PayerAuthenticationIdentityCardMismatch | The payment failed payer authentication (e.g. failed 3DS) due to payer abandoning or canceling the authentication flow, or the required authentication is not supported. |

### Insufficient Balance

| `result` | `source` | `detail` | description |
| - | :- | :- | - |
| InsufficientBalance | Customer | InsufficientBalance | |

### Fraud Risk

| `result` | `possible sources` | `detail` | description |
| - | - | - | - |
| FraudRisk | Acquirer Issuer Provider | FraudRiskBlockList FraudRiskScore FraudRiskRule FraudRiskSecurity FraudRiskSuspectedFraud | |


## Related topics

- [Get Fraud Operations by Fraud ID](/reference/getfraudoperations.md)
- [Get Payment Operations by Payment ID](/reference/getpaymentoperations.md)
- [Get ThreeDS Operations by ThreeDS ID](/reference/getthreedsoperations.md)
