Custom Categories

Custom categories let a team define its own fraud patterns from example phrases, called scenarios. Once a category is ready, it is scored alongside the built-in catalog — or instead of it, if the team has disabled the built-ins with Team Settings.

Embedding lifecycle

Categories embed asynchronously after creation. A category is only used for scoring once its status is ready.

StatusMeaning
pendingCreated; embedding has not started.
embeddingExample phrases are being embedded.
readyAvailable for scoring.
needs_more_examplesToo few scenarios to score reliably.
failedThe embed job errored. See embed_error.

List categories

Returns the team’s settings, the built-in categories, the team’s custom categories with their scenarios and overlap warnings, and calibration status.

GET https://app.resemble.ai/api/v2/signal/custom_categories

$curl --request GET 'https://app.resemble.ai/api/v2/signal/custom_categories' \
> -H 'Authorization: Bearer YOUR_API_TOKEN'
1{
2 "success": true,
3 "settings": { "use_builtin_categories": true },
4 "built_in_categories": [
5 {
6 "id": 7,
7 "name": "CEO Impersonation / Wire Diversion",
8 "icon": "👔",
9 "scenario_count": 24,
10 "example_texts": ["transfer the funds immediately", "send the wire today"]
11 }
12 ],
13 "custom_categories": [
14 {
15 "id": 99,
16 "name": "Tech Support Scam",
17 "status": "ready",
18 "enabled": true,
19 "scenario_count": 2,
20 "overlaps": [],
21 "scenarios": [
22 { "id": 501, "text": "Your computer has a virus, press 1 to continue", "embedded": true }
23 ]
24 }
25 ],
26 "calibration": {
27 "status": "completed",
28 "calibrated_at": "2026-06-14T10:00:00.000Z",
29 "overall_recall": 0.94,
30 "warnings": []
31 }
32}

calibration is null until the team’s categories have been calibrated. overlaps lists calibration warnings where this category was confused with another one.

Create a category

POST https://app.resemble.ai/api/v2/signal/custom_categories

Request parameters

FieldTypeRequiredDescription
namestringYesCategory name. Must be unique within the team.
scenariosstring[]YesExample phrases that define the pattern. Maximum 50, each up to 2000 characters. A newline-separated string is also accepted.
descriptionstringNoFree-form description.
iconstringNoSingle emoji.
enabledbooleanNoWhether to include the category in scoring. Defaults to true.
$curl --request POST 'https://app.resemble.ai/api/v2/signal/custom_categories' \
> -H 'Authorization: Bearer YOUR_API_TOKEN' \
> -H 'Content-Type: application/json' \
> --data '{
> "name": "Tech Support Scam",
> "icon": "☎️",
> "description": "Calls impersonating tech support",
> "scenarios": [
> "Your computer has a virus, press 1 to continue",
> "We detected suspicious activity, verify your identity now"
> ]
> }'

Response

1{
2 "success": true,
3 "item": {
4 "id": 99,
5 "name": "Tech Support Scam",
6 "description": "Calls impersonating tech support",
7 "icon": "☎️",
8 "enabled": true,
9 "status": "pending",
10 "embed_error": null,
11 "embedded_at": null,
12 "scenario_count": 2,
13 "embedding_model_version": null,
14 "overlaps": [],
15 "scenarios": [
16 { "id": 501, "text": "Your computer has a virus, press 1 to continue", "embedded": false },
17 { "id": 502, "text": "We detected suspicious activity, verify your identity now", "embedded": false }
18 ]
19 }
20}

Response fields

FieldTypeDescription
item.idintegerCategory identifier.
item.namestringCategory name.
item.descriptionstring | nullFree-form description.
item.iconstring | nullSingle emoji.
item.enabledbooleanWhether the category is included in scoring.
item.statusstringEmbedding status. See Embedding lifecycle.
item.embed_errorstring | nullError message when status is failed.
item.embedded_atstring | nullWhen embedding completed.
item.scenario_countintegerNumber of example phrases.
item.embedding_model_versionstring | nullModel version used to embed the scenarios.
item.overlapsarrayCalibration warnings where this category was confused with another.
item.scenariosarrayExample phrases, each with id, text, and whether it has embedded.

Validation errors return 422 Unprocessable Entity:

1{
2 "success": false,
3 "message": "Too many scenarios — max 50"
4}

Get a category

GET https://app.resemble.ai/api/v2/signal/custom_categories/{id}

$curl --request GET 'https://app.resemble.ai/api/v2/signal/custom_categories/99' \
> -H 'Authorization: Bearer YOUR_API_TOKEN'

Returns the same item shape as create. Unknown identifiers return 404 Not Found.

Update a category

PATCH https://app.resemble.ai/api/v2/signal/custom_categories/{id}

Accepts any subset of the create parameters.

$curl --request PATCH 'https://app.resemble.ai/api/v2/signal/custom_categories/99' \
> -H 'Authorization: Bearer YOUR_API_TOKEN' \
> -H 'Content-Type: application/json' \
> --data '{ "enabled": false }'

Supplying scenarios replaces the entire example set and re-triggers embedding. The category returns to pending until embedding completes.

Delete a category

DELETE https://app.resemble.ai/api/v2/signal/custom_categories/{id}

$curl --request DELETE 'https://app.resemble.ai/api/v2/signal/custom_categories/99' \
> -H 'Authorization: Bearer YOUR_API_TOKEN'
1{
2 "success": true
3}