curl --request POST \
--url https://api.tryfuse.ai/api/v1/business/prospects/search/save-to-list \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--data '{
"limit": 5000
}'import requests
url = "https://api.tryfuse.ai/api/v1/business/prospects/search/save-to-list"
payload = { "limit": 5000 }
headers = {
"Authorization": "Basic <encoded-value>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Basic <encoded-value>', 'Content-Type': 'application/json'},
body: JSON.stringify({limit: 5000})
};
fetch('https://api.tryfuse.ai/api/v1/business/prospects/search/save-to-list', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"listIds": [
"6a8da255c5017e82fb66df5d"
],
"enrich": "phone_and_email",
"totalContacts": 500,
"estimatedMinutes": 25,
"campaign": {
"id": "6a8da7718707dbcfb4448b96",
"attached": true
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}Save people-search results into a list
Run the search server-side and save up to limit matches into a contact list. The filter source is exactly one of filters, a saved search (savedSearchId / savedSearchName), or a natural-language query — the same contract as POST /prospects/search. The destination is exactly one of listId or listName; listName is create-or-reuse by exact name (case-insensitive), a name shared by two lists is a 409, and system list names are refused.
enrich selects what runs on the saved rows: none (default) saves the search rows as-is at 2 credits per row; email, phone or phone_and_email run the enrichment waterfall while saving (50 / 200 / 250 credits per row pre-checked), and rows already carrying the requested data are not re-charged. Only the enrichment modes report totalContacts and estimatedMinutes.
An optional campaignId XOR campaignName attaches the destination list to that campaign in the same motion, and the response’s campaign.attached says whether that succeeded — a failed attach never retracts a started save. The attach happens when the save STARTS: a draft campaign enrols the full list at approval, while an ACTIVE non-dynamic campaign enrols only the rows present at attach time.
Always async: 202 means the job started, not that the list is populated — poll the list’s rows. Billing: this runs its own search, it does NOT reuse a prior POST /prospects/search, so previewing first and then saving pays for the search twice. Saving a hand-picked subset of results is not supported; narrow the filters instead.
Errors:
402INSUFFICIENT_CREDITS— The balance does not cover the pre-check for this request; nothing was billed.404SAVED_SEARCH_NOT_FOUND— No saved search of yours has that id or exact title.404CAMPAIGN_NOT_FOUND— No campaign of yours matchescampaignId/campaignName; nothing was saved.409SAVED_SEARCH_NAME_AMBIGUOUS— Two of your saved searches share that title — reference it bysavedSearchIdinstead.409CAMPAIGN_NAME_AMBIGUOUS— Two of your campaigns share that name — passcampaignIdinstead.409LIST_NAME_AMBIGUOUS— Two of your lists share that name — passlistIdinstead.409ALL_CONTACTS_ALREADY_ENRICHED— Every matching row already carries the requested enrichment — nothing to run and nothing billed.422VALIDATION_FAILED— The request failed the declared schema;paramnames the offending key andmessagequotes the rule it broke.422SAVED_SEARCH_TYPE_MISMATCH— The saved search exists but stores the other kind of filters;paramissavedSearchId.422SAVED_SEARCH_INVALID— The STORED filters no longer form a runnable search — every value was retired, or the blob translates to nothing.422QUERY_FILTERS_INVALID— The natural-languagequeryproduced no usable filter; name concrete criteria.422LIST_NAME_RESERVED—listNameis a system/dynamic list title and cannot be a destination.422CAMPAIGN_LIST_CAP_REACHED— The campaign already holds the maximum number of attached lists; nothing was saved.429RATE_LIMITED— Per-token rate limit for this bucket exhausted; retry after the window in the RateLimit-Reset header.500UNEXPECTED_ERROR— The request failed inside the service; nothing was billed and the request_id identifies the failure.
Requires one of the following token scopes: search.
curl --request POST \
--url https://api.tryfuse.ai/api/v1/business/prospects/search/save-to-list \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--data '{
"limit": 5000
}'import requests
url = "https://api.tryfuse.ai/api/v1/business/prospects/search/save-to-list"
payload = { "limit": 5000 }
headers = {
"Authorization": "Basic <encoded-value>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Basic <encoded-value>', 'Content-Type': 'application/json'},
body: JSON.stringify({limit: 5000})
};
fetch('https://api.tryfuse.ai/api/v1/business/prospects/search/save-to-list', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"listIds": [
"6a8da255c5017e82fb66df5d"
],
"enrich": "phone_and_email",
"totalContacts": 500,
"estimatedMinutes": 25,
"campaign": {
"id": "6a8da7718707dbcfb4448b96",
"attached": true
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}Authorizations
Your API token (af_…) as the Basic-auth username, with an empty password.
Body
Exactly one filter source (filters | savedSearchId | savedSearchName | query), exactly one destination (listId | listName), an optional campaign (campaignId | campaignName, never both), plus limit and enrich.
Maximum number of matching profiles to save (1-10000). Credits are pre-checked per row before the job starts: 2 with enrich: none, otherwise the enrichment price per row (402 INSUFFICIENT_CREDITS when the balance is short).
1 <= x <= 10000Literal filters, one of the four filter sources — the same vocabulary as POST /prospects/search. People filters in the search vocabulary: include/exclude fields take [{ status, value }] entries, term fields a string or an array of strings, rangeInputs { min, max } ranges — every field and its accepted values are listed by GET /prospects/filter-options. On this endpoint a value outside a field's listed vocabulary is refused with 422 VALIDATION_FAILED, naming the field and the value, before anything is billed. Must contain at least one non-empty value.
Show child attributes
Show child attributes
Id of one of your PEOPLE saved searches to take the filters from instead of filters (a company saved search answers 422 SAVED_SEARCH_TYPE_MISMATCH).
Exact title of one of your people saved searches to take the filters from instead of filters; two searches sharing the title answer 409 SAVED_SEARCH_NAME_AMBIGUOUS.
1 - 255Natural-language description of who to find (max 2000 chars), converted into filters server-side instead of filters; criteria that could not be mapped come back as unresolvedCriteria, and a query yielding no filter answers 422 QUERY_FILTERS_INVALID.
1 - 2000Id of an existing contact list to save into (exactly one of listId / listName).
Name of the destination contact list, created when none exists; an existing list with the same name (case-insensitive) is reused, a name shared by several lists answers 409 LIST_NAME_AMBIGUOUS, and system list names answer 422 LIST_NAME_RESERVED.
1 - 255What to run on the saved rows: none (default) saves the search rows as-is for 2 credits per row; email (pre-checks 50 credits per row), phone (200) or phone_and_email (250) run the enrichment waterfall while saving — rows already carrying the requested data are not re-charged.
none, email, phone, phone_and_email Id of one of your campaigns to attach the destination list to once the save has started (optional; exactly one of campaignId / campaignName).
Exact name of one of your campaigns to attach the destination list to (optional); no match answers 404 CAMPAIGN_NOT_FOUND and a shared name 409 CAMPAIGN_NAME_AMBIGUOUS.
1 - 255Response
Success
Destination list ids the save is writing into (the reused list, or the one just created).
Echo of the enrichment mode the job is running.
none, email, phone, phone_and_email Enrichment modes only: how many rows the job will process.
Enrichment modes only: rough completion estimate.
Only when a campaign was requested.
Show child attributes
Show child attributes