Skip to main content
This guide covers category action triggers. For an overview of all trigger types, see the Action triggers guide. For merchant action triggers, see the Merchant action triggers guide.

Overview

Category action triggers let you register rules that fire custom actions when transactions are enriched into specific Spade categories. Triggers match on Spade’s category taxonomy rather than individual merchants, so a single trigger can cover every merchant in a category — to target specific merchants instead, see merchant action triggers. Common use cases:
  • Category-based rewards: 3x points on all Travel transactions
  • Spending controls: Block all Gambling transactions
  • Category allowlists: Only allow transactions in approved categories (e.g., Fuel, Office Supplies)

Quick Start

  1. Discover categories — Call GET /categories to get the list of available category IDs
  2. Register triggers — Use the PUT endpoint with your category trigger configuration
  3. Enrich transactions — Matched triggers appear in the actions field of the enrichment response
  4. (Optional) Update triggers incrementally — Use the PATCH endpoint to add or remove individual triggers without re-registering the full list

Discovering categories

Use the GET /categories endpoint to retrieve the full list of Spade categories. Each category has an id that you’ll use as the categoryId when registering triggers.
curl --request GET \
  --url https://east.api.spade.com/categories \
  --header 'X-Api-Key: YOUR_API_KEY'
The response includes category IDs and names:
[
  {
    "id": "020-001-000-000",
    "name": "Travel",
    "icon": "https://static.v2.spadeapi.com/categories/..."
  },
  {
    "id": "019-001-000-000",
    "name": "Gambling",
    "icon": "https://static.v2.spadeapi.com/categories/..."
  }
]
Use the id value as the categoryId in your trigger registrations.

Registration Scopes

Category action triggers can be registered at four scopes. See the Action triggers guide for how scope inheritance works.
ScopeEndpointLimit
Account/category-action-triggers300 triggers
Program/programs/{programId}/category-action-triggers300 triggers
User/users/{userId}/category-action-triggers300 triggers
Card/users/{userId}/cards/{cardId}/category-action-triggers300 triggers
All registrations are processed synchronously — there is no batch processing. Status will be succeeded immediately upon a successful request.

Registering category action triggers

Use the PUT endpoint to register category action triggers.
PUT replaces your entire trigger list. Every PUT request overwrites all previously registered triggers at that scope. If you need to add or remove a few triggers, use the PATCH endpoint instead.See the API reference for PATCH endpoint details.

Request body

Each trigger requires:
  • id — Your unique identifier for this trigger (max 512 characters)
  • categoryId — A valid Spade category ID (use GET /categories to discover valid IDs)
  • action — Your custom action data (same semantics as merchant triggers)
You do not need to provide a categoryName — it is resolved from the system during enrichment and returned in the response.

Example: REWARD trigger on Travel

curl --request PUT \
  --url https://east.api.spade.com/category-action-triggers \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: YOUR_API_KEY' \
  --data '{
    "categoryTriggers": [
      {
        "id": "travel-reward",
        "categoryId": "020-001-000-000",
        "action": {
          "type": "REWARD",
          "rewardPercent": 3,
          "offerId": "travel-3x-promo"
        }
      }
    ]
  }'

Example: BLOCK trigger on Gambling

curl --request PUT \
  --url https://east.api.spade.com/category-action-triggers \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: YOUR_API_KEY' \
  --data '{
    "categoryTriggers": [
      {
        "id": "block-gambling",
        "categoryId": "019-001-000-000",
        "action": {
          "type": "BLOCK",
          "reason": "Gambling transactions not permitted"
        }
      }
    ]
  }'

Response

{
  "status": "succeeded",
  "version": 1
}

Checking Registration Status

Use the GET endpoint to check the status of your category action trigger registration.

Status Values

StatusDescription
succeededRegistration complete, triggers are now active
failedRegistration failed, check your request and retry
Since category trigger registrations are processed synchronously, the status is succeeded or failed immediately after a PUT or PATCH request.
Important: Triggers are only applied to enrichment responses when the status is succeeded.

Example: Check Status

curl --request GET \
  --url https://east.api.spade.com/category-action-triggers \
  --header 'X-Api-Key: YOUR_API_KEY'

Response

{
  "status": "succeeded",
  "version": 1,
  "categoryTriggers": [
    {
      "id": "travel-reward",
      "action": { "type": "REWARD", "rewardPercent": 3, "offerId": "travel-3x-promo" }
    },
    {
      "id": "block-gambling",
      "action": { "type": "BLOCK", "reason": "Gambling transactions not permitted" }
    }
  ],
  "totalCount": 2
}

Updating Triggers

Use the PATCH endpoint to incrementally add or remove triggers without replacing the entire list.

Adding triggers

Use operation: "add" with categoryTriggers to register new triggers or update existing ones. If a trigger ID already exists, its registration is replaced (upsert behavior).
curl --request PATCH \
  --url https://east.api.spade.com/category-action-triggers \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: YOUR_API_KEY' \
  --data '{
    "operation": "add",
    "categoryTriggers": [
      {
        "id": "groceries-reward",
        "categoryId": "005-001-000-000",
        "action": {
          "type": "REWARD",
          "rewardPercent": 2,
          "offerId": "groceries-2x"
        }
      }
    ]
  }'

Removing triggers

Use operation: "remove" with triggerIds to deactivate triggers. Trigger IDs that are not currently active are silently ignored (idempotent).
curl --request PATCH \
  --url https://east.api.spade.com/category-action-triggers \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: YOUR_API_KEY' \
  --data '{
    "operation": "remove",
    "triggerIds": ["block-gambling"]
  }'

Clearing Triggers

Use the DELETE endpoint to clear all category triggers at a given scope.
DELETE creates a new version with an empty trigger list. The version number is incremented, not reset.

Example: Clear Account-Scoped Triggers

curl --request DELETE \
  --url https://east.api.spade.com/category-action-triggers \
  --header 'X-Api-Key: YOUR_API_KEY'

ALLOW_ONLY Inverse Semantics

When category triggers use ALLOW_ONLY, the behavior inverts for non-matching transactions:
  • Transaction in a registered category: authRecommendation: "ALLOW"
  • Transaction in any other category: authRecommendation: "BLOCK", source: null
This allows you to create category allowlists where only transactions in approved categories are permitted.

Example: Allow only Fuel and Office Supplies

curl --request PUT \
  --url https://east.api.spade.com/category-action-triggers \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: YOUR_API_KEY' \
  --data '{
    "categoryTriggers": [
      {
        "id": "allow-fuel",
        "categoryId": "016-001-000-000",
        "action": { "type": "ALLOW_ONLY" }
      },
      {
        "id": "allow-office",
        "categoryId": "010-001-000-000",
        "action": { "type": "ALLOW_ONLY" }
      }
    ]
  }'

Receiving Triggered Actions

When a transaction matches a category trigger, the enrichment response includes the trigger in the actions array with type: "category_trigger". Category triggers include additional categoryId and categoryName fields.

Example: Enrichment Response with Category Trigger

{
  "enrichmentId": "d1f7490c-719e-4c75-8bfa-535c8a32b936",
  "transactionInfo": {
    "type": "spending",
    "display": {
      "name": "United Airlines",
      "categoryName": "Travel"
    }
  },
  "actions": [
    {
      "id": "travel-reward",
      "type": "category_trigger",
      "action": {
        "type": "REWARD",
        "rewardPercent": 3,
        "offerId": "travel-3x-promo"
      },
      "scope": "account",
      "source": "counterparty",
      "categoryId": "020-001-000-000",
      "categoryName": "Travel"
    }
  ]
}

Example: Both Merchant and Category Triggers

When a transaction matches both merchant and category triggers, all matched triggers appear in the actions array:
{
  "enrichmentId": "a2b3c4d5-e6f7-8901-abcd-ef2345678901",
  "transactionInfo": {
    "type": "spending",
    "display": {
      "name": "Starbucks",
      "categoryName": "Coffee Shop"
    }
  },
  "actions": [
    {
      "id": "starbucks-reward",
      "type": "merchant_trigger",
      "action": {
        "type": "REWARD",
        "rewardPercent": 5,
        "offerId": "summer-2024-promo"
      },
      "scope": "account",
      "source": "counterparty"
    },
    {
      "id": "dining-reward",
      "type": "category_trigger",
      "action": {
        "type": "REWARD",
        "rewardPercent": 2,
        "offerId": "dining-2x"
      },
      "scope": "program",
      "source": "counterparty",
      "categoryId": "008-001-000-000",
      "categoryName": "Coffee Shop"
    }
  ]
}
The actions field is null when no triggers match, and is omitted entirely if your account does not have the actions feature enabled.

Best Practices

Unique Trigger IDs

Trigger IDs must be unique within each scope. A scope is defined by the URL path you register against (account, program, user, or card level).
  • Within a single request: All trigger IDs must be unique. Duplicate IDs in the same request will return a 400 error.
  • Across requests in the same scope: Submitting a trigger with an ID that already exists in that scope will replace the previous registration (upsert). This applies to both PUT (full replacement) and PATCH add operations.
  • Across different scopes: The same trigger ID can be used independently in different scopes without conflict.

Action Structure

Design your action schema upfront. This is your custom data — use it to store reward amounts, offer IDs, or any information you need when processing matched transactions. The type field is required. Reserved keywords (BLOCK, ALLOW_ONLY) have special authorization behavior. REWARD and all other values are passed through as-is.

Scope Selection

  • Use account scope for triggers that apply to all users (e.g., company-wide category restrictions)
  • Use program scope for triggers scoped to a specific program (e.g., different reward tiers per card product)
  • Use user scope for user-specific preferences
  • Use card scope for card-specific rules (e.g., a dedicated rewards card with higher multipliers)

Choosing PUT vs. PATCH

  • Use PUT when replacing your full set of triggers (e.g., initial setup or a periodic full sync)
  • Use PATCH when adding or removing a small number of triggers relative to your total list

Error Handling

  • Implement retry logic for 5xx errors
  • Handle 409 Conflict by waiting for the in-progress registration to complete
  • Validate your trigger data before submission to avoid 400 errors