Scan history for a single profile remains on GET /api/v1/members/{member_id}/scans/. This route only queues scans.
| Resource | Path | Purpose |
|---|---|---|
| Scan one member | /api/v1/members/{member_id}/scan/{product_id}/ |
POST spend one credit of that product and queue a scan |
| Scan many members | /api/v1/scan/ |
POST spend one credit per member for many member_ids or account_ids |
Auth: Bearer token required. See Authentication.
Products are in Products. Subscriptions scan on a built-in cadence. On-demand scans spend credits assigned to the member from the org pool (Purchase credits).
POST /api/v1/members/{member_id}/scan/{product_id}/
{product_id} is an on-demand product on the member. Spends one credit and queues a scan of that product’s catalog.
POST /api/v1/members/67890/scan/201/
202 Accepted){
"member_id": 67890,
"product_id": 201,
"credits_remaining": 0
}
The spend is listed on GET /api/v1/members/{member_id}/credits/{product_id}/. Job status is on GET /api/v1/members/{member_id}/scans/.
| Status | Condition |
|---|---|
400 |
{product_id} is not an on-demand product on the member |
401 |
Missing or invalid API key |
402 |
No credits left on that product and no active subscription (error: no_actions) |
403 |
Partner inactive |
404 |
Member or product not found |
When the request fails, no scan is queued and no credit is spent.
To scan many members at once, use POST /api/v1/scan/ with member_ids or account_ids.
POST /api/v1/scan/
Queues a scan for every member in member_ids, or every member on each account in account_ids, and spends one credit per member. A credit is one full scan of that product’s catalog, using every identifier on the profile. Kanary selects the site mix in that catalog. Scanning by a specific site id or domain is not supported.
After the scan is accepted, for each member queued:
product.credits_remaining decreases by one.GET /api/v1/members/{member_id}/credits/{product_id}/.credits_remaining is then 0 and the account has no active subscription, it has no actions available.The product object stays as it is. Login is unchanged. Profile updates still work. Another scan needs credits_remaining greater than 0. Assign more credits for the same product, set a different on-demand product, or set a subscription. See Add a product.
tier must match the scan product’s product_tier. Every account in the scope must hold that product and have enough credits for the members being queued. A shortfall fails the request and spends nothing.
Provide exactly one scope: account_ids or member_ids. Combining them, or sending neither, returns 400.
| Scope | Body | Who is scanned |
|---|---|---|
| Accounts | account_ids: array of integers |
Every member on each account. One credit per member |
| Members | member_ids: array of integers |
The listed profiles. One credit per profile, from credits assigned to that member |
Accounts and members must belong to your partner. Unknown or out-of-scope ids return 404 (same as other id-scoped routes—see Authentication — Resource access).
| Field | Required | Type | Description |
|---|---|---|---|
tier |
Yes | string | "core", "advanced", or "trial". Must match product.product_tier. Selects that on-demand product on the member |
account_ids |
One of | array of integers | Scan the accounts whose active product matches tier |
member_ids |
One of | array of integers | Scan these member profiles. Consumes the on-demand product on each of their accounts |
account_ids or member_ids is required. The array must be non-empty. Sending both returns 400.
By account ids — Core Scan on those accounts:
POST /api/v1/scan/
Content-Type: application/json
Authorization: Bearer <api_key>
{
"tier": "core",
"account_ids": [12345, 12346]
}
By member ids — Advanced Scan:
POST /api/v1/scan/
Content-Type: application/json
Authorization: Bearer <api_key>
{
"tier": "advanced",
"member_ids": [67890, 67891]
}
202 Accepted)Scans are queued asynchronously. Poll GET .../members/{member_id}/scans/ for job status and GET /api/v1/members/{member_id}/credits/{product_id}/ for the balance.
{
"tier": "core",
"scope": "account_ids",
"credits_consumed": 3,
"members_queued": 3,
"member_ids": [67890, 67891, 67892],
"accounts": [
{
"account_id": 12345,
"credits_consumed": 2,
"credits_remaining": 0,
"status": "ACTIVE"
},
{
"account_id": 12346,
"credits_consumed": 1,
"credits_remaining": 4,
"status": "ACTIVE"
}
]
}
| Field | Type | Description |
|---|---|---|
tier |
string | "core", "advanced", or "trial" |
scope |
string | Which scope was applied: "account_ids" or "member_ids" |
credits_consumed |
integer | Credits spent (one per member queued) |
members_queued |
integer | Number of members for which scan jobs were queued |
member_ids |
array of integers | Member ids that were queued |
accounts |
array | Per account: account_id, credits_consumed, credits_remaining, status (unchanged; "ACTIVE" when the balance hits 0) |
Per-site progress for any member is on GET .../members/{member_id}/scans/.
| Status | Condition |
|---|---|
400 |
Missing/invalid tier; missing account_ids and member_ids, or both sent; empty account_ids / member_ids; an account in scope holds a subscription product or its product_tier does not match tier; a Trial Scan member has no phone or name to scan on (error: trial_identifier_required) |
401 |
Missing or invalid API key |
403 |
Partner inactive |
402 |
An account in scope has no credits and no active subscription (error: no_actions; includes account_ids and message: This account has no actions available.). Or the scope needs more credits than credits_remaining (error: insufficient_scan_credits; includes tier, required, available, account_id) |
404 |
One or more account or member ids not found / not accessible to your partner |
When the request fails, no scan is queued and no credit is spent.
{
"error": "no_actions",
"message": "This account has no actions available.",
"account_ids": [12346]
}