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

# Authorization Webhook Overview

> Use authorization webhooks to approve or decline card transactions in real-time.

<Note>
  **Enterprise Feature**: Authorization webhooks are an enterprise-only feature. Please reach out to [sales@slash.com](mailto:sales@slash.com) to get set up with this functionality.
</Note>

## Overview

Authorization webhooks allow you to implement real-time transaction approval logic by receiving authorization requests before transactions are processed. When a card transaction is initiated, Slash will send a webhook to your configured endpoint, allowing you to approve or decline the transaction based on your custom business logic.

## Setup

To begin receiving authorization webhook requests, you'll need to configure an authorization webhook URL for your account using the [account authorization webhook endpoints](/api-reference/account-authorization-webhook-put).

## Webhook Headers

Every authorization webhook request includes three important headers for security and validation:

* **`x-webhook-id`**: A unique identifier for the webhook request
* **`x-webhook-timestamp`**: The timestamp when the webhook was sent (Unix timestamp)
* **`x-webhook-signature`**: HMAC signature for request validation

## Request Validation

### Timestamp Validation

The `x-webhook-timestamp` should be within 2 minutes of receiving the request to prevent replay attacks.

### Signature Validation

To verify that the webhook request actually came from Slash, you should validate the `x-webhook-signature` header using HMAC SHA256. The signature is created by:

1. Removing the `whsec_` prefix from your signing secret and base64 decoding it
2. Creating a payload string: `{webhookId}.{webhookTimestamp}.{requestBody}`
3. Generating an HMAC SHA256 signature using the decoded secret
4. Base64 encoding the signature and prefixing with `v1=`

Here's a complete example of signature validation:

```javascript theme={null}
import crypto from 'crypto';

function validateWebhookSignature(webhookId, webhookTimestamp, signature, body, signingSecret) {
  // Remove whsec_ prefix from signing secret if present
  const secretBase64 = signingSecret.replace('whsec_', '');
  
  // Decode the base64 secret to get the actual signing key
  const decodedSecret = Buffer.from(secretBase64, 'base64');
  
  // Create the payload to sign: webhookId.webhookTimestamp.body
  const payload = `${webhookId}.${webhookTimestamp}.${body}`;
  
  // Generate HMAC SHA256 signature using the decoded secret
  const expectedSignature = crypto
    .createHmac('sha256', decodedSecret)
    .update(payload)
    .digest('base64');
  
  // Extract signature from header (remove 'v1=' prefix)
  const receivedSignature = signature.replace('v1=', '');
  
  // Compare signatures using timing-safe comparison
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature, 'base64'),
    Buffer.from(receivedSignature, 'base64')
  );
}
```

## Request Timeout

Authorization webhook requests have a default timeout of **1.5 seconds**. Your endpoint must respond within this timeframe, or the transaction will be automatically decisioned based on your [fallback behavior](#fallback-behavior).

## Response Format

Your webhook endpoint must return a **2xx HTTP status code** to indicate successful processing. Any non-2xx response will be treated as a failed request.

The response body must contain your authorization decision. See the [Authorization Webhook Response schema](/api-reference/schema-authorization-webhook-response) for the complete response format.

Example approval response:

```json theme={null}
{
  "approved": true,
  "reason": "Transaction approved"
}
```

Example decline response:

```json theme={null}
{
  "approved": false,
  "reason": "Insufficient funds"
}
```

## Event Schema

The webhook request body contains detailed information about the authorization request. See the [Authorization Request Event schema](/api-reference/schema-authorization-request-event) for the complete structure of the event data sent to your webhook.

## Debugging and Monitoring

When debugging your authorization webhook behavior, you can view the approval or decline reason directly in the transaction details. This helps you understand how your webhook responses are being processed and troubleshoot any issues.

<img src="https://mintcdn.com/slash-9da6c7e7/dljaI9moim4tgYyE/images/external-webhook-approved-reason.png?fit=max&auto=format&n=dljaI9moim4tgYyE&q=85&s=f009fa0d3391242fafba7b285f5cea9f" alt="External Webhook Approval Reason" width="800" height="56" data-path="images/external-webhook-approved-reason.png" />

## Fallback Behavior

If your webhook endpoint is unreachable, returns a non-2xx status code, returns an invalid response body, or times out, the transaction will be automatically handled based on your webhook config's `fallbackBehavior`:

* `default`: Your transaction will continue to go through our authorization flow (balance and limit checks still apply), and will be treated as if you approved it.
* `reject`: Your transaction will be declined.

The same fallback is applied in the rare case that Slash is operating in a degraded mode where external webhooks cannot be consulted at all — so the fallback you configure fully describes what happens whenever we cannot get an answer from your endpoint.

```json theme={null}
{
  "fallbackBehavior": "reject"
}
```

### Conditional fallback with `when`

When using `fallbackBehavior: "default"`, you can optionally restrict which transactions are allowed to continue by providing a `when` condition expression. Transactions matching the condition continue through the standard authorization flow; non-matching transactions are declined. If `when` is omitted, every transaction continues (the default behavior).

`when` is a small expression tree:

| Node              | Shape                                                                                                   | Semantics                                               |
| ----------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| Logical           | `{ "operator": "and" \| "or", "left": <condition>, "right": <condition> }`                              | Combines two sub-conditions; nestable                   |
| Amount comparison | `{ "operator": "lte" \| "lt" \| "gte" \| "gt" \| "eq", "field": "amountCents", "value": <integer> }`    | Compares the absolute transaction amount in USD cents   |
| Set membership    | `{ "operator": "in", "field": "merchantCategoryCode" \| "merchantCountry", "values": [<string>, ...] }` | Matches when the transaction's field is one of `values` |

* `merchantCategoryCode` is the 4-digit MCC and `merchantCountry` is the ISO 3166-1 alpha-2 country, exactly as delivered on the [Authorization Request Event](/api-reference/schema-authorization-request-event) (`merchant.categoryCode` and `merchant.location.country`).
* A condition over a field the authorization request did not carry evaluates to false (the transaction is declined rather than allowed through).

For example, to auto-approve fallback transactions only when they are at most \$20.00 **and** from MCC 7311:

```json theme={null}
{
  "fallbackBehavior": "default",
  "when": {
    "operator": "and",
    "left": { "operator": "lte", "field": "amountCents", "value": 2000 },
    "right": { "operator": "in", "field": "merchantCategoryCode", "values": ["7311"] }
  }
}
```

Or to continue for small transactions **or** any US transaction:

```json theme={null}
{
  "fallbackBehavior": "default",
  "when": {
    "operator": "or",
    "left": { "operator": "lte", "field": "amountCents", "value": 1000 },
    "right": { "operator": "in", "field": "merchantCountry", "values": ["US"] }
  }
}
```

The `when` condition only applies to the fallback path — if your endpoint responds in time with a valid decision, that decision is always respected. See the [Authorization Webhook schema](/api-reference/schema-authorization-webhook) for the full config format.
