Manage Keyword Sets
Use the Keyword Sets endpoints to create keyword sets, change their keywords and seed URLs, and read them back. Keyword sets you manage here are the same ones you see in the Demandbase One UI.
Beta: These endpoints are in beta and may change before general availability.
Before you begin
Generate a Demandbase API token using Authenticate with Demandbase APIs and replace YOUR_ACCESS_TOKEN with it. Your API key set must include Intent API access.
Important: Intent API access includes write access. Any API key set with Intent API access can create and change keyword sets, not only read intent data.
Create a keyword set
curl --request POST \
--url https://uapi.demandbase.com/data/intent/v1/keyword-sets \
--header "Authorization: Bearer YOUR_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data '{
"name": "Cloud Security Vendors",
"keywords": ["zero trust", "casb", "sase"]
}'name and keywords are required. keywords may be an empty array. isCompetitor is optional and defaults to false. seedUrls is optional; see Add a seed URL.
Names must be unique within your tenant. Keywords are trimmed and de-duplicated without regard to case, so the created set may hold fewer keywords than you sent.
Example response
{
"id": 9427,
"name": "Cloud Security Vendors",
"isCompetitor": false,
"keywords": [
{ "id": 551201, "keyword": "zero trust", "createdAt": "2026-08-20T09:14:22Z", "updatedAt": "2026-08-20T09:14:22Z" },
{ "id": 551202, "keyword": "casb", "createdAt": "2026-08-20T09:14:22Z", "updatedAt": "2026-08-20T09:14:22Z" },
{ "id": 551203, "keyword": "sase", "createdAt": "2026-08-20T09:14:22Z", "updatedAt": "2026-08-20T09:14:22Z" }
],
"seedUrls": [],
"createdAt": "2026-08-20T09:14:22Z",
"updatedAt": "2026-08-20T09:14:22Z"
}A successful create returns 201 Created with the full keyword set. Save the id; you use it in every other request for this set.
Add and remove keywords
curl --request PATCH \
--url https://uapi.demandbase.com/data/intent/v1/keyword-sets/9427 \
--header "Authorization: Bearer YOUR_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data '{
"keywords": {
"add": ["microsegmentation", "ztna"],
"remove": ["legacy vpn"]
}
}'Every property is optional, and any property you omit keeps its stored value. Send at least one of name, isCompetitor, keywords, or seedUrls.
| Property | Effect |
|---|---|
name | Replaces the name |
isCompetitor | Replaces the flag; existing keywords are not changed |
keywords.add | Adds keywords not already present, ignoring case |
keywords.remove | Removes matching keywords, ignoring case |
seedUrls.add | Attaches seed URLs not already attached, matched exactly |
seedUrls.remove | Detaches matching seed URLs, matched exactly |
Adding a value that is already present, or removing one that is not, succeeds without changing anything. You can therefore resend the same update after a timeout. The same value cannot appear in both add and remove.
A successful update returns 200 OK with the full keyword set, including every keyword and seed URL.
Add a seed URL
{
"seedUrls": { "add": ["https://example.com/security"] }
}Adding a seed URL generates related keywords while the request waits, so the request takes noticeably longer than other calls. Generation adds up to 100 keywords per request in total, skips keywords the set already holds, and does not run again for a URL that is already attached.
The http or https scheme is optional and the host must contain a dot. Seed URLs are stored exactly as sent, so https://Example.com/a and https://example.com/a are different seed URLs.
Important: An update that adds a seed URL is rejected with
400-249unless the set has room for 100 more keywords. A create does not make this check, so a newly created set can hold up to 100 keywords more than the per-set limit. Until you remove enough keywords, updates that add keywords or seed URLs to that set are rejected.
Read keyword sets
List keyword-set metadata, optionally filtered by name:
curl --request GET \
--url "https://uapi.demandbase.com/data/intent/v1/keyword-sets?name=Cloud%20Security&sortBy=name&sortOrder=ASC" \
--header "Authorization: Bearer YOUR_ACCESS_TOKEN" \
--header "Accept: application/json"To read one keyword set's metadata, send its ID as ?id=9427. There is no separate get-by-ID endpoint.
List items never include keywords or seed URLs. Read those through their own endpoints, which page independently:
curl --request GET \
--url "https://uapi.demandbase.com/data/intent/v1/keyword-sets/9427/keywords?page=1&perPage=100" \
--header "Authorization: Bearer YOUR_ACCESS_TOKEN" \
--header "Accept: application/json"{
"keywords": [
{ "id": 551201, "keyword": "zero trust", "createdAt": "2026-08-20T09:14:22Z", "updatedAt": "2026-08-20T09:14:22Z" },
{ "id": 551202, "keyword": "casb", "createdAt": "2026-08-20T09:14:22Z", "updatedAt": "2026-08-20T09:14:22Z" }
],
"pageNo": 1,
"pageSize": 100,
"totalCount": 5
}Seed URLs work the same way at /keyword-sets/9427/seed-urls. An unknown keyword-set ID returns 404-106. A name search with no matches returns 200 OK with an empty array.
Use a keyword set in an intent query
Pass the keyword set's id in keywordSetIds when you retrieve company intent data:
{
"keywordSetIds": [9427],
"startDate": "2026-07-01",
"endDate": "2026-07-22"
}Delete a keyword set
There is no delete endpoint in this version. To delete a keyword set, use the Demandbase One UI. To empty a set, remove its keywords and seed URLs with an update.
Write safely
- Send one write at a time to any one keyword set. Concurrent updates that remove keywords or change seed URLs on the same set can overwrite each other.
- Concurrent creates with the same name can fail with
500instead of409-101. - A request rejected with a
4xxstatus never changes anything. A write that fails with500or504may have been partly applied, so read the set back before you retry.
For the complete request and response schema, see the Keyword Sets reference.
Updated 12 minutes ago