Category Personalization Guide
ⓘ Reading Time: 10 mins
Category personalization is released in beta.
Category personalization makes it easy to customize Spade's categorization system to support additional use cases. Key features include:
- Creating custom categories at the integration-level
- Creating custom categories at the user-level
- Recategorizing individual transactions with default and/or custom categories
- Recategorizing future transactions with default and/or custom categories based on the counterparty
This guide walks you through creating custom categories and recategorizing transactions at the integration-level. For information on creating user-level categories and personalizations, please see the User Category Personalization Guide.
Category personalization is not enabled by default. To request access, please contact us at [email protected].
Fetch the default categories for your integration
The first thing you’ll likely want to do is fetch the default categories for your integration. This list contains all of the categories that Spade provides, plus any custom categories that you’ve added at integration-level (which should be none at this point).
import requests
response = requests.get("https://east.sandbox.spade.com/categories", headers={"X-Api-Key": "<Your API Key Here>"})
print(response.json())
Sending the above request returns a list containing all of Spade's 250+ categories:
[
{
"id": "001-000-000-000",
"name": "Banking and Finance",
"icon": "https://static.v2.spadeapi.com/categories/61897b3a5af545bab45ca1bf20498e65/light.png",
"fullCategoryHierarchy": [
{
"id": "001-000-000-000",
"name": "Banking and Finance",
"icon": "https://static.v2.spadeapi.com/categories/61897b3a5af545bab45ca1bf20498e65/light.png"
}
]
},
{
"id": "001-001-000-000",
"name": "Accounting and Bookkeeping",
"icon": "https://static.v2.spadeapi.com/categories/61897b3a5af545bab45ca1bf20498e65/light.png",
"fullCategoryHierarchy": [
{
"id": "001-000-000-000",
"name": "Banking and Finance",
"icon": "https://static.v2.spadeapi.com/categories/61897b3a5af545bab45ca1bf20498e65/light.png"
},
{
"id": "001-001-000-000",
"name": "Accounting and Bookkeeping",
"icon": "https://static.v2.spadeapi.com/categories/61897b3a5af545bab45ca1bf20498e65/light.png"
}
]
},
...
]
Note that Spade’s categories are hierarchical, so Accounting and Bookkeeping
, for instance, sits underneath the Banking and Finance
category, which sits at the root level. For convenience, each serialized category includes a fullCategoryHierarchy
object, which contains the full hierarchy of the category.
Creating a custom category
Spade's default categories are designed to meet the majority of use cases. However, there are some use cases where you may want to create custom categories specific to your integration. Custom categories can sit at the root level, under Spade's categories, or under other custom integration-level categories. Here’s how you can create a custom category that sits at the root level:
import requests
custom_category = {
"name": "Family",
"parentId": ""
}
response = requests.post("https://east.sandbox.spade.com/categories", json=custom_category, headers={"X-Api-Key": "<Your API Key Here>"})
print(response.json())
Sending the above request creates a new custom category and returns a copy of the serialized category:
{
"id": "7235be6a-669c-47f2-9ab6-cac3f3edbab9",
"name": "Family",
"icon": null,
"fullCategoryHierarchy": [
{
"id": "7235be6a-669c-47f2-9ab6-cac3f3edbab9",
"name": "Family",
"icon": null
}
]
}
Here’s how you can create a custom category that sits under this category:
import requests
custom_category = {
"name": "Day Care",
"parentId": "7235be6a-669c-47f2-9ab6-cac3f3edbab9" # Replace with the ID of the category you just created
}
response = requests.post("https://east.sandbox.spade.com/categories", json=custom_category, headers={"X-Api-Key": "<Your API Key Here>"})
print(response.json())
Sending the above request creates the new custom category and returns a copy of the serialized category:
{
"id": "ba8d4e26-052a-4260-bcf4-6523469fcf48",
"name": "Day Care",
"icon": null,
"fullCategoryHierarchy": [
{
"id": "7235be6a-669c-47f2-9ab6-cac3f3edbab9",
"name": "Family",
"icon": null
},
{
"id": "ba8d4e26-052a-4260-bcf4-6523469fcf48",
"name": "Day Care",
"icon": null
}
]
}
Re-fetching the default categories for your integration
Now, if you re-fetch the default categories for your integration, you'll see the two custom categories you just created:
import requests
response = requests.get("https://east.sandbox.spade.com/categories", headers={"X-Api-Key": "<Your API Key Here>"})
print(response.json())
Sending the above request returns a list containing all of Spade's 250+ categories plus the new custom categories:
[
// Spade's default categories will show up first
{
"id": "001-000-000-000",
"name": "Banking and Finance",
"icon": "https://static.v2.spadeapi.com/categories/61897b3a5af545bab45ca1bf20498e65/light.png",
"fullCategoryHierarchy": [
{
"id": "001-000-000-000",
"name": "Banking and Finance",
"icon": "https://static.v2.spadeapi.com/categories/61897b3a5af545bab45ca1bf20498e65/light.png"
}
]
},
{
"id": "001-001-000-000",
"name": "Accounting and Bookkeeping",
"icon": "https://static.v2.spadeapi.com/categories/61897b3a5af545bab45ca1bf20498e65/light.png",
"fullCategoryHierarchy": [
{
"id": "001-000-000-000",
"name": "Banking and Finance",
"icon": "https://static.v2.spadeapi.com/categories/61897b3a5af545bab45ca1bf20498e65/light.png"
},
{
"id": "001-001-000-000",
"name": "Accounting and Bookkeeping",
"icon": "https://static.v2.spadeapi.com/categories/61897b3a5af545bab45ca1bf20498e65/light.png"
}
]
},
...
// Your integration's custom categories will show up next
{
"id": "7235be6a-669c-47f2-9ab6-cac3f3edbab9",
"name": "Family",
"icon": null,
"fullCategoryHierarchy": [
{
"id": "7235be6a-669c-47f2-9ab6-cac3f3edbab9",
"name": "Family",
"icon": null
}
]
},
{
"id": "ba8d4e26-052a-4260-bcf4-6523469fcf48",
"name": "Day Care",
"icon": null,
"fullCategoryHierarchy": [
{
"id": "7235be6a-669c-47f2-9ab6-cac3f3edbab9",
"name": "Family",
"icon": null
},
{
"id": "ba8d4e26-052a-4260-bcf4-6523469fcf48",
"name": "Day Care",
"icon": null
}
]
}
]
Notice that custom category IDs are UUIDs, while Spade's default categories use a hierarchical numerical ID system. This is by design: our system uses different ID formats for custom and default categories to make it easy for you to distinguish between the two.
Recategorizing past transactions
To recategorize specific past transactions onto a custom category, you’ll want to update those transaction records in your internal system. For instance:
import requests
# Update each transaction's category in your internal system.
# Note that the PATCH body will depend on your internal data schema.
requests.patch(
"https://your.backend.com/enriched-transactions/1234",
{
"category": [
{
"id": "ba8d4e26-052a-4260-bcf4-6523469fcf48",
"name": "Day Care",
"icon": null
}
]
},
headers=YOUR_AUTH_HEADERS,
)
Recategorizing all future transactions for a specific counterparty
One of the most powerful features Spade provides is the ability for you to recategorize future transactions before they take place. This feature takes advantage of Spade’s ability to consistently match transactions to stable counterparty IDs using ground truth data.
Here’s how you can recategorize future transactions for a specific counterparty across your entire integration:
import requests
counterparty_category_personalization = {
# KinderCare Learning Centers
"counterpartyId": "1d4cb97d-939e-36e7-b3aa-d7116af2f87c",
# Day Care
"categoryId": "ba8d4e26-052a-4260-bcf4-6523469fcf48"
}
requests.put("https://east.sandbox.spade.com/counterparty-category-personalization", json=counterparty_category_personalization, headers={"X-Api-Key": "<Your API Key Here>"})
With this personalization in place, any future transactions that take place at KinderCare Learning Centers
will be enriched with the custom category, which will appear in the personalization
section of the enrichment as the counterparty's industry
:
{
"transactionInfo": {
"type": "spending",
"thirdParties": [],
"spendingInfo": {
"channel": {
"value": "digital"
}
},
"transactionId": "cb1d4fc5-6d72-4d67-a911-d479c96b30b2",
"irregularWebPresenceDetected": false,
"recurrenceInfo": null
},
"counterparty": [
{
"id": "1d4cb97d-939e-36e7-b3aa-d7116af2f87c",
"name": "Kindercare Learning Centers",
"legalName": "KinderCare Learning Companies, Inc.",
// Spade still returns the original industry here so you can use it for internal analysis
"industry": [
{
"id": "012-000-000-000",
"name": "Services",
"icon": "https://static.dev.v2.spadeapi.com/categories/922d5d4ec3a64304a93723bea02d3890/light.png"
},
{
"id": "012-010-000-000",
"name": "Household Services",
"icon": "https://static.dev.v2.spadeapi.com/categories/922d5d4ec3a64304a93723bea02d3890/light.png"
},
{
"id": "012-010-001-000",
"name": "Childcare",
"icon": "https://static.dev.v2.spadeapi.com/categories/922d5d4ec3a64304a93723bea02d3890/light.png"
}
],
"location": [
{
"id": "cfec00c3-c1e0-3d38-97dd-65769bd10c71",
"address": "650 NE Holladay St Suite 100",
"addressLine1": "650 NE Holladay St",
"addressLine2": "Suite 100",
"city": "Portland",
"region": "OR",
"postalCode": "97232",
"country": "USA",
"phoneNumber": null,
"latitude": 45.529718,
"longitude": -122.659176,
"matchScore": null
}
],
"matchScore": 97.76,
"logo": "https://static.v2.spadeapi.com/logos/1d4cb97d939e36e7b3aad7116af2f87c/light.png",
"medianSpendPerTransaction": null,
"phoneNumber": null,
"website": "kindercare.com"
}
],
"personalization": {
"counterparty": [
{
"id": "1d4cb97d-939e-36e7-b3aa-d7116af2f87c",
// Here's the personalized category
"industry": [
{
"id": "7235be6a-669c-47f2-9ab6-cac3f3edbab9",
"name": "Family",
"icon": null
},
{
"id": "ba8d4e26-052a-4260-bcf4-6523469fcf48",
"name": "Day Care",
"icon": null
}
]
}
]
},
"enrichmentId": "4f88dd8d-8d0f-4e3a-b2cf-8d4ba686d667"
}
Deleting custom categories
You can delete custom categories all at once or individually.
To delete all custom integration-level categories, send a DELETE
request to the categories
endpoint:
import requests
requests.delete("https://east.sandbox.spade.com/categories", headers={"X-Api-Key": "<Your API Key Here>"})
To delete a specific custom integration-level category, send a DELETE
request to the categories/:id
endpoint with the category's ID:
import requests
requests.delete("https://east.sandbox.spade.com/categories/aeb3b2e5-c46d-417c-9513-62868a6b0410", headers={"X-Api-Key": "<Your API Key Here>"})
Any custom integration-level or user-level categories that were children of the deleted integration-level categories will automatically have their
parentId
set to an empty string (i.e. they will become root-level categories).
Deleting counterparty category personalizations
You can delete counterparty category personalizations all at once or individually.
To delete all counterparty category personalizations, send a DELETE
request to the /counterparty-category-personalizations
endpoint:
import requests
requests.delete("https://east.sandbox.spade.com/counterparty-category-personalizations", headers={"X-Api-Key": "<Your API Key Here>"})
To delete a specific counterparty category personalization, send a DELETE
request to the /counterparty-category-personalizations/:counterpartyId
endpoint with the counterpartyId
of the personalization you want to delete:
import requests
requests.delete("https://east.sandbox.spade.com/counterparty-category-personalizations/ec5ac9b9-0ea5-4248-a666-3197d945b85a", headers={"X-Api-Key": "<Your API Key Here>"})
FAQs
What if I want to recategorize transactions based on the industry instead of the counterparty?
We don't currently support category-wide personalizations. However, you can achieve this on your end by creating Spade category -> custom category mappings on your end.
Conclusion
You've just learned how Spade's category personalization endpoints can be used to create custom categories at the integration-level and recategorize transactions onto those categories.