Browse the docs

Reference · 13 operations

Actions: lists and find

Last updated from API version 2026-10-06 at (live spec, refreshed hourly). openapi.json

Find

actions.find.provider_id

Resolve a LinkedIn profile URL to its provider id.

post/api/v1/actions/find/provider_id
Scope
read
Credits
See the catalog entry
Idempotency-Key
optional
Class
read
Approval floor
none
Runs
Inline for one target, else async
Targets
contact, contacts, records
Max targets
100
Dry run
Supported

Read class, free. Looks each target's LinkedIn URL up through one LinkedIn account of this workspace: the key's bound identity, else identityId (a session defaults to the signed-in member's own identity). Never another workspace's account; no profile-view notification is sent. Targets: a contact (its LinkedIn URL), contacts, or up to 100 inline records with linkedinUrl. One target runs inline (200 {data: {action, result}}); dryRun: true (or Owlbound-Dry-Run: true) returns the plan and calls nothing. More than one target (or mode: "async") creates an async run: 202 {data: {action}} with Location: /api/v1/actions/{id}; the targets run in batches of 25 and their outcomes are on GET /actions/{id}/targets and GET /events. A deployment without the async runner answers 503 ACTIONS_ASYNC_UNAVAILABLE and creates nothing. A dry run stores its plan for 15 minutes; a real call with that planId (or Owlbound-Plan) runs only if the targets, skip set, input, approval outcome and credit maximum still match, else 409 PLAN_STALE with the new plan in error.details.plan. A plan runs once (409 PLAN_ALREADY_APPLIED) and only for the key, session or agent run that made it. 4xx answers are stored under the Idempotency-Key: apply a new planId with a new Idempotency-Key. After a key rotation the old key keeps its plans during the grace period; the new key gets 404 for them.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

FindProviderIdRequest

  • targetone ofrequired
    0
    + Show child fields
  • No options; the LinkedIn URL comes from each target.

    0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose LinkedIn account runs the lookup. A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); an unbound key must name one (422 IDENTITY_REQUIRED); a session defaults to the member's own.

    0

Responses

200
The finished action and its result, or the dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
An async run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/find/provider_id" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "target": {
    "kind": "contact",
    "contactId": "<contactId>"
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

actions.find.linkedin_url

Find a person's LinkedIn profile URL.

post/api/v1/actions/find/linkedin_url
Scope
enrich
Credits
20 credits per target
Idempotency-Key
required
Class
spend
Approval floor
none
Runs
Inline for one target, else async
Targets
contact, contacts, records
Max targets
1,000
Dry run
Supported
Writes back
contact

Spend class. Runs a waterfall per target and stops at the first URL whose confidence is at least input.minConfidence (default medium): internal (this workspace's own contacts, free), then apollo and zoominfo with the workspace's own connected keys (BYOK, free), then linkedin_search, a name search on the identity's own LinkedIn account (20 credits, enrichment.linkedin_url.find, charged only when it finds the URL). Override the order with input.providers. Confidence: high for the contact's own URL or an email match, medium for a name with the company, low for a name alone. Nothing found is free. Targets: a contact, contacts, or up to 100 inline records with firstName and lastName (and company, domain) or email; a contact that already has a LinkedIn URL is answered from it, free. A found URL is written onto a contact target per output.contact (default fillEmpty). The LinkedIn search spends one of the account's 150 daily LinkedIn lookups; without an identity with an active LinkedIn account it is skipped. One target runs inline (200 {data: {action, result}}, one target's price held then settled at what it was charged); more (or mode: "async") create an async run (202), billed per batch of 25. dryRun: true returns the plan with the credit maximum and calls nothing.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

FindLinkedInUrlRequest

  • targetone ofrequired
    0
    + Show child fields
  • 0
  • 0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose LinkedIn account runs the linkedin_search step. A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); a session defaults to the member's own. Without a usable identity the search step is skipped.

    0

Responses

200
The finished action and its result, or the dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
An async run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 402 Not enough credits (INSUFFICIENT_CREDITS). With an Idempotency-Key this result is stored and replayed: after adding credits, retry with a new Idempotency-Key. · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/find/linkedin_url" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "target": {
    "kind": "contact",
    "contactId": "<contactId>"
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

actions.find.public_url

Resolve a Sales Navigator profile URL to its public LinkedIn URL.

post/api/v1/actions/find/public_url
Scope
read
Credits
See the catalog entry
Idempotency-Key
optional
Class
read
Approval floor
none
Runs
Inline for one target, else async
Targets
contact, contacts, records
Max targets
100
Dry run
Supported

Read class, free. Reads each Sales Navigator profile through one LinkedIn account of this workspace (the key's bound identity, else identityId; a session defaults to the member's own), never another workspace's, with no profile-view notification. Each lookup spends one of the account's 150 daily LinkedIn lookups; a URL that is already public is answered as is, free. Targets: a contact (its stored Sales Navigator URL), contacts, or up to 100 inline records with salesNavUrl. One target runs inline; more create an async run (202). dryRun: true returns the plan and calls nothing.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

FindPublicUrlRequest

  • targetone ofrequired
    0
    + Show child fields
  • No options; the Sales Navigator URL comes from each target.

    0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose LinkedIn account runs the lookup. A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); an unbound key must name one (422 IDENTITY_REQUIRED); a session defaults to the member's own.

    0

Responses

200
The finished action and its result, or the dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
An async run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/find/public_url" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "target": {
    "kind": "contact",
    "contactId": "<contactId>"
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

actions.find.company_ids

Find LinkedIn company ids for a company name.

post/api/v1/actions/find/company_ids
Scope
read
Credits
See the catalog entry
Idempotency-Key
optional
Class
read
Approval floor
none
Runs
Inline for one target, else async
Targets
records
Max targets
100
Dry run
Supported

Read class, free. Looks each query up in LinkedIn's company search through one LinkedIn account of this workspace (the key's bound identity, else identityId; a session defaults to the member's own). The result is up to 25 companies {id, name, logoUrl} (ids for the companyIds filter of actions.lists.linkedin_search); no match is a success with no companies. Targets: up to 100 inline records with query (1 to 100 characters). One target runs inline; more create an async run (202). dryRun: true returns the plan and calls nothing.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

FindCompanyIdsRequest

  • 0
  • No options; the query comes from each record.

    0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose LinkedIn account runs the search. A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); an unbound key must name one (422 IDENTITY_REQUIRED); a session defaults to the member's own.

    0

Responses

200
The finished action and its result, or the dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
An async run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/find/company_ids" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "target": {
    "kind": "records",
    "records": [
      {
        "query": "<query>"
      }
    ]
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

Lists

actions.lists.sales_nav

A list of people from a Sales Navigator URL.

post/api/v1/actions/lists/sales_nav
Scope
enrich
Credits
12 credits per call + 3 credits per record (quantity from input.maxResults)
Idempotency-Key
required
Class
spend
Approval floor
none
Runs
Async
Targets
none
Max targets
100
Dry run
Supported
Writes back
contact
Max duration
7200 s

A Sales Navigator people search (read through our data provider) or saved lead list (read through the identity's own LinkedIn account with Sales Navigator: the key's bound identity, else identityId). URLs over 4,000 characters are 422 SALES_NAV_URL_TOO_LONG; company searches are 422 LIST_SOURCE_UNSUPPORTED. Spend class, async only (202 {data: {action}}, Location: /api/v1/actions/{id}); target none (the list makes its own targets: one per provider page, run in order). Price audience.scrape.start: 12 per list plus 3 per person written, charged per page once the page is written (a person already written by an earlier page of the same list is not charged again; a page that writes nobody is free), held per batch of pages, never above maxCredits (pages that would pass it are skipped RUN_CAPPED) or the key's daily credit cap (CAP_EXCEEDED). dryRun: true counts the search once with the provider (reused for 15 minutes, also by the call that applies the plan) and returns the pages and the credit estimate; nothing is held or written. The people land in the list's items (read by the list-to-table writer) and, for an audience, in its contacts. Cancel stops at the next page.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

ListsSalesNavRequest

  • inputListsSalesNavInputrequired
    0
  • Lists make their own targets (one per provider page).

    0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose connected LinkedIn account runs the search (sources read through your LinkedIn account only). A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); an unbound key must name one (422 IDENTITY_REQUIRED); a session defaults to the member's own.

    0
  • maxCreditsnumber

    Caps the list's credits (default and ceiling the plan's estimatedMax).

    min 0
  • Where the people land besides the list's items. table writes one row per person into a table of this workspace (not available yet for some workspaces: 409 TABLE_STORE_UNSUPPORTED): {tableId} uses its columns that match (key, else name, with a type that takes the value; the plan lists the fields left unmapped), {create: {name}} makes a table with every list column (first name, last name, title, company, location, LinkedIn URL, Sales Navigator URL, profile picture, LinkedIn provider id). Rows are matched by the person (a re-run fills empty cells, never duplicates). contacts: true pushes the rows to contacts (the table push, fill empty fields) when the list finishes; it needs table and the push rule (owner, admin or leader), checked again when the list finishes. Any output needs the write scope as well as enrich (403 INSUFFICIENT_SCOPE). The push outcome (pushed, refused and failed rows, last error code) is on the action's result.contactsPush. Company lists (lists.companies) write company columns instead (name, LinkedIn URL, industry, location, employees, followers, description, logo, LinkedIn provider id), never contacts; their companies: true finds or creates each company in the workspace's companies (by LinkedIn URL, empty fields filled) and links its table row (write scope; allowed without a table). Website-visitor lists write company columns plus domain and visits, each row linked to the workspace's company; never contacts.

    0
  • schedulestring | null

    Refreshing lists are not available yet (422 SCHEDULE_UNAVAILABLE).

    0

Responses

200
The dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
The list run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/lists/sales_nav" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "input": {
    "url": "https://example.com"
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

actions.lists.icp

Scrape a saved audience (ICP) into its contacts.

post/api/v1/actions/lists/icp
Scope
enrich
Credits
12 credits per call + 3 credits per record (quantity from input.maxPages)
Idempotency-Key
required
Class
spend
Approval floor
none
Runs
Async
Targets
none
Max targets
100
Dry run
Supported
Writes back
contact
Max duration
7200 s

Runs the audience's search (its Sales Navigator URL, or its criteria compiled to one) and imports the people into the workspace's contacts as members of the audience, as the app's scrape does. An audience being scraped is 409 LIST_BUSY; a first scrape of an audience over 1,000 people is 422 ICP_TOO_BROAD; company audiences are 422 LIST_SOURCE_UNSUPPORTED. maxPages pages of 25 (10 for saved lead lists). Spend class, async only (202 {data: {action}}, Location: /api/v1/actions/{id}); target none (the list makes its own targets: one per provider page, run in order). Price audience.scrape.start: 12 per list plus 3 per person written, charged per page once the page is written (a person already written by an earlier page of the same list is not charged again; a page that writes nobody is free), held per batch of pages, never above maxCredits (pages that would pass it are skipped RUN_CAPPED) or the key's daily credit cap (CAP_EXCEEDED). dryRun: true counts the search once with the provider (reused for 15 minutes, also by the call that applies the plan) and returns the pages and the credit estimate; nothing is held or written. The people land in the list's items (read by the list-to-table writer) and, for an audience, in its contacts. Cancel stops at the next page.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

ListsIcpRequest

  • inputListsIcpInputrequired
    0
  • Lists make their own targets (one per provider page).

    0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose connected LinkedIn account runs the search (sources read through your LinkedIn account only). A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); an unbound key must name one (422 IDENTITY_REQUIRED); a session defaults to the member's own.

    0
  • maxCreditsnumber

    Caps the list's credits (default and ceiling the plan's estimatedMax).

    min 0
  • Where the people land besides the list's items. table writes one row per person into a table of this workspace (not available yet for some workspaces: 409 TABLE_STORE_UNSUPPORTED): {tableId} uses its columns that match (key, else name, with a type that takes the value; the plan lists the fields left unmapped), {create: {name}} makes a table with every list column (first name, last name, title, company, location, LinkedIn URL, Sales Navigator URL, profile picture, LinkedIn provider id). Rows are matched by the person (a re-run fills empty cells, never duplicates). contacts: true pushes the rows to contacts (the table push, fill empty fields) when the list finishes; it needs table and the push rule (owner, admin or leader), checked again when the list finishes. Any output needs the write scope as well as enrich (403 INSUFFICIENT_SCOPE). The push outcome (pushed, refused and failed rows, last error code) is on the action's result.contactsPush. Company lists (lists.companies) write company columns instead (name, LinkedIn URL, industry, location, employees, followers, description, logo, LinkedIn provider id), never contacts; their companies: true finds or creates each company in the workspace's companies (by LinkedIn URL, empty fields filled) and links its table row (write scope; allowed without a table). Website-visitor lists write company columns plus domain and visits, each row linked to the workspace's company; never contacts.

    0
  • schedulestring | null

    Refreshing lists are not available yet (422 SCHEDULE_UNAVAILABLE).

    0

Responses

200
The dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
The list run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/lists/icp" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "input": {
    "icpProfileId": "<icpProfileId>"
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

actions.lists.companies

A list of companies from a LinkedIn company search.

post/api/v1/actions/lists/companies
Scope
enrich
Credits
12 credits per call + 3 credits per record (quantity from input.maxResults)
Idempotency-Key
required
Class
spend
Approval floor
none
Runs
Async
Targets
none
Max targets
100
Dry run
Supported
Max duration
7200 s

A list of companies from a LinkedIn company search (Sales Navigator by default, or classic) on the identity's own LinkedIn account (the key's bound identity, else identityId); it spends the account's daily search budget (429 LINKEDIN_SEARCH_LIMIT). At least keywords or one filter. The companies land in the list's items and, with output.table, in a table with company columns (name, LinkedIn URL, industry, location, employees, followers, description, logo, LinkedIn provider id); output.companies: true also finds or creates each company in the workspace's companies (by LinkedIn URL, empty fields filled, nothing overwritten) and links its row. A company list never writes contacts (output.contacts is 400). Spend class, async only (202 {data: {action}}, Location: /api/v1/actions/{id}); target none (the list makes its own targets: one per page of 25, run in order). Price audience.scrape.start: 12 per list plus 3 per record written, charged per page once the page is written (a record already written by an earlier page of the same list is not charged again; a page that writes nothing is free), held per batch of pages, never above maxCredits (pages that would pass it are skipped RUN_CAPPED) or the key's daily credit cap (CAP_EXCEEDED). Cancel stops at the next page. dryRun: true counts the search once with the provider (reused for 15 minutes, also by the call that applies the plan) and returns the pages and the credit estimate; nothing is held or written.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

ListsCompaniesRequest

  • inputListsCompaniesInputrequired

    At least keywords or one filter.

    0
  • Lists make their own targets (one per provider page).

    0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose connected LinkedIn account runs the search (sources read through your LinkedIn account only). A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); an unbound key must name one (422 IDENTITY_REQUIRED); a session defaults to the member's own.

    0
  • maxCreditsnumber

    Caps the list's credits (default and ceiling the plan's estimatedMax).

    min 0
  • Where the people land besides the list's items. table writes one row per person into a table of this workspace (not available yet for some workspaces: 409 TABLE_STORE_UNSUPPORTED): {tableId} uses its columns that match (key, else name, with a type that takes the value; the plan lists the fields left unmapped), {create: {name}} makes a table with every list column (first name, last name, title, company, location, LinkedIn URL, Sales Navigator URL, profile picture, LinkedIn provider id). Rows are matched by the person (a re-run fills empty cells, never duplicates). contacts: true pushes the rows to contacts (the table push, fill empty fields) when the list finishes; it needs table and the push rule (owner, admin or leader), checked again when the list finishes. Any output needs the write scope as well as enrich (403 INSUFFICIENT_SCOPE). The push outcome (pushed, refused and failed rows, last error code) is on the action's result.contactsPush. Company lists (lists.companies) write company columns instead (name, LinkedIn URL, industry, location, employees, followers, description, logo, LinkedIn provider id), never contacts; their companies: true finds or creates each company in the workspace's companies (by LinkedIn URL, empty fields filled) and links its table row (write scope; allowed without a table). Website-visitor lists write company columns plus domain and visits, each row linked to the workspace's company; never contacts.

    0
  • schedulestring | null

    Refreshing lists are not available yet (422 SCHEDULE_UNAVAILABLE).

    0

Responses

200
The dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
The list run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/lists/companies" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "input": {
    "keywords": "<keywords>",
    "locationIds": [
      "<locationIds>"
    ],
    "industryIds": [
      "<industryIds>"
    ]
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

actions.lists.company_employees

A list of one company's employees.

post/api/v1/actions/lists/company_employees
Scope
enrich
Credits
12 credits per call + 3 credits per record (quantity from input.limit)
Idempotency-Key
required
Class
spend
Approval floor
none
Runs
Async
Targets
none
Max targets
100
Dry run
Supported
Writes back
contact
Max duration
7200 s

Everyone at one company (our data provider's employee search, no title filter), up to limit (at most 100) people. The company is input.company: exactly one of its LinkedIn numeric linkedinId, its domain or its LinkedIn company url (looked up once and reused for 15 minutes; no match is 404 NOT_FOUND). Runs on our data provider, no LinkedIn account: on the workspace's own data provider key when it has one (free), else on Owlbound's, where uncached company lookups and searches are limited per workspace and day (429 PROVIDER_DAILY_LIMIT) and a wallet with no credits gets no lookup (a dry run returns the estimate without the count, warning COUNT_UNKNOWN; a real call is 402). The search runs once for every person asked for, never more than maxCredits pays for (on page 1, which may wait up to a few minutes for it), so the wallet must hold the whole estimate before the list starts: otherwise 402 INSUFFICIENT_CREDITS (details.required, details.available), and a dry-run warning. The people land in the list's items and, with output.table, in a table (the people columns); output.contacts pushes them when the list finishes. Spend class, async only (202 {data: {action}}, Location: /api/v1/actions/{id}); target none (the list makes its own targets: one per page of 25, run in order). Price audience.scrape.start: 12 per list plus 3 per record written, charged per page once the page is written (a record already written by an earlier page of the same list is not charged again; a page that writes nothing is free), held per batch of pages, never above maxCredits (pages that would pass it are skipped RUN_CAPPED) or the key's daily credit cap (CAP_EXCEEDED). Cancel stops at the next page. dryRun: true returns the pages and the estimate from the company's size (the lookup only; no search runs); nothing is held or written.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

ListsCompanyEmployeesRequest

  • 0
  • Lists make their own targets (one per provider page).

    0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose connected LinkedIn account runs the search (sources read through your LinkedIn account only). A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); an unbound key must name one (422 IDENTITY_REQUIRED); a session defaults to the member's own.

    0
  • maxCreditsnumber

    Caps the list's credits (default and ceiling the plan's estimatedMax).

    min 0
  • Where the people land besides the list's items. table writes one row per person into a table of this workspace (not available yet for some workspaces: 409 TABLE_STORE_UNSUPPORTED): {tableId} uses its columns that match (key, else name, with a type that takes the value; the plan lists the fields left unmapped), {create: {name}} makes a table with every list column (first name, last name, title, company, location, LinkedIn URL, Sales Navigator URL, profile picture, LinkedIn provider id). Rows are matched by the person (a re-run fills empty cells, never duplicates). contacts: true pushes the rows to contacts (the table push, fill empty fields) when the list finishes; it needs table and the push rule (owner, admin or leader), checked again when the list finishes. Any output needs the write scope as well as enrich (403 INSUFFICIENT_SCOPE). The push outcome (pushed, refused and failed rows, last error code) is on the action's result.contactsPush. Company lists (lists.companies) write company columns instead (name, LinkedIn URL, industry, location, employees, followers, description, logo, LinkedIn provider id), never contacts; their companies: true finds or creates each company in the workspace's companies (by LinkedIn URL, empty fields filled) and links its table row (write scope; allowed without a table). Website-visitor lists write company columns plus domain and visits, each row linked to the workspace's company; never contacts.

    0
  • schedulestring | null

    Refreshing lists are not available yet (422 SCHEDULE_UNAVAILABLE).

    0

Responses

200
The dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
The list run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/lists/company_employees" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "input": {
    "company": {
      "linkedinId": "<linkedinId>",
      "domain": "<domain>",
      "url": "https://example.com"
    }
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

actions.lists.decision_makers

A list of one company's decision makers.

post/api/v1/actions/lists/decision_makers
Scope
enrich
Credits
12 credits per call + 3 credits per record (quantity from input.limit)
Idempotency-Key
required
Class
spend
Approval floor
none
Runs
Async
Targets
none
Max targets
100
Dry run
Supported
Writes back
contact
Max duration
7200 s

The decision makers of one company: our data provider's employee search filtered by titleKeywords (default Founder, Chief, President, Vice President, VP, Director, Head, Owner, Partner, Manager), up to limit (at most 50) people. The company is input.company: exactly one of its LinkedIn numeric linkedinId, its domain or its LinkedIn company url (looked up once and reused for 15 minutes; no match is 404 NOT_FOUND). Runs on our data provider, no LinkedIn account: on the workspace's own data provider key when it has one (free), else on Owlbound's, where uncached company lookups and searches are limited per workspace and day (429 PROVIDER_DAILY_LIMIT) and a wallet with no credits gets no lookup (a dry run returns the estimate without the count, warning COUNT_UNKNOWN; a real call is 402). The search runs once for every person asked for, never more than maxCredits pays for (on page 1, which may wait up to a few minutes for it), so the wallet must hold the whole estimate before the list starts: otherwise 402 INSUFFICIENT_CREDITS (details.required, details.available), and a dry-run warning. The people land in the list's items and, with output.table, in a table (the people columns); output.contacts pushes them when the list finishes. Spend class, async only (202 {data: {action}}, Location: /api/v1/actions/{id}); target none (the list makes its own targets: one per page of 25, run in order). Price audience.scrape.start: 12 per list plus 3 per record written, charged per page once the page is written (a record already written by an earlier page of the same list is not charged again; a page that writes nothing is free), held per batch of pages, never above maxCredits (pages that would pass it are skipped RUN_CAPPED) or the key's daily credit cap (CAP_EXCEEDED). Cancel stops at the next page. dryRun: true returns the pages and the estimate from the company's size (the lookup only; no search runs); nothing is held or written.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

ListsDecisionMakersRequest

  • 0
  • Lists make their own targets (one per provider page).

    0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose connected LinkedIn account runs the search (sources read through your LinkedIn account only). A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); an unbound key must name one (422 IDENTITY_REQUIRED); a session defaults to the member's own.

    0
  • maxCreditsnumber

    Caps the list's credits (default and ceiling the plan's estimatedMax).

    min 0
  • Where the people land besides the list's items. table writes one row per person into a table of this workspace (not available yet for some workspaces: 409 TABLE_STORE_UNSUPPORTED): {tableId} uses its columns that match (key, else name, with a type that takes the value; the plan lists the fields left unmapped), {create: {name}} makes a table with every list column (first name, last name, title, company, location, LinkedIn URL, Sales Navigator URL, profile picture, LinkedIn provider id). Rows are matched by the person (a re-run fills empty cells, never duplicates). contacts: true pushes the rows to contacts (the table push, fill empty fields) when the list finishes; it needs table and the push rule (owner, admin or leader), checked again when the list finishes. Any output needs the write scope as well as enrich (403 INSUFFICIENT_SCOPE). The push outcome (pushed, refused and failed rows, last error code) is on the action's result.contactsPush. Company lists (lists.companies) write company columns instead (name, LinkedIn URL, industry, location, employees, followers, description, logo, LinkedIn provider id), never contacts; their companies: true finds or creates each company in the workspace's companies (by LinkedIn URL, empty fields filled) and links its table row (write scope; allowed without a table). Website-visitor lists write company columns plus domain and visits, each row linked to the workspace's company; never contacts.

    0
  • schedulestring | null

    Refreshing lists are not available yet (422 SCHEDULE_UNAVAILABLE).

    0

Responses

200
The dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
The list run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/lists/decision_makers" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "input": {
    "company": {
      "linkedinId": "<linkedinId>",
      "domain": "<domain>",
      "url": "https://example.com"
    }
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

actions.lists.post_engagers

A list of the people who engaged with a LinkedIn post.

post/api/v1/actions/lists/post_engagers
Scope
enrich
Credits
12 credits per call + 3 credits per record (quantity from input.maxResults)
Idempotency-Key
required
Class
spend
Approval floor
none
Runs
Async
Targets
none
Max targets
100
Dry run
Supported
Writes back
contact
Max duration
7200 s

The people who commented on or reacted to one LinkedIn post (a post URL or urn:li: id, or userPostId, one of the workspace's published posts), at most 100 comments and 100 reactions as the app reads them; only people with a profile URL, each once. Read on the identity's own LinkedIn account (the key's bound identity, else identityId); the count and every page spend the account's daily search budget (429 LINKEDIN_SEARCH_LIMIT). The people land in the list's items and, with output.table, in a table (the people columns); output.contacts pushes them when the list finishes. Spend class, async only (202 {data: {action}}, Location: /api/v1/actions/{id}); target none (one target per page of 25, run in order). Price audience.scrape.start: 12 per list plus 3 per person written, charged per page once the page is written (a person an earlier page wrote is not charged again; a page that writes nobody is free), never above maxCredits or the key's daily credit cap. dryRun: true reads the post's comment and reaction counts once (reused for 15 minutes) and returns the pages and the credit estimate; nothing is held or written. Cancel stops at the next page.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

ListsPostEngagersRequest

  • Exactly one of postUrl or userPostId.

    0
  • Lists make their own targets (one per provider page).

    0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose connected LinkedIn account runs the search (sources read through your LinkedIn account only). A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); an unbound key must name one (422 IDENTITY_REQUIRED); a session defaults to the member's own.

    0
  • maxCreditsnumber

    Caps the list's credits (default and ceiling the plan's estimatedMax).

    min 0
  • Where the people land besides the list's items. table writes one row per person into a table of this workspace (not available yet for some workspaces: 409 TABLE_STORE_UNSUPPORTED): {tableId} uses its columns that match (key, else name, with a type that takes the value; the plan lists the fields left unmapped), {create: {name}} makes a table with every list column (first name, last name, title, company, location, LinkedIn URL, Sales Navigator URL, profile picture, LinkedIn provider id). Rows are matched by the person (a re-run fills empty cells, never duplicates). contacts: true pushes the rows to contacts (the table push, fill empty fields) when the list finishes; it needs table and the push rule (owner, admin or leader), checked again when the list finishes. Any output needs the write scope as well as enrich (403 INSUFFICIENT_SCOPE). The push outcome (pushed, refused and failed rows, last error code) is on the action's result.contactsPush. Company lists (lists.companies) write company columns instead (name, LinkedIn URL, industry, location, employees, followers, description, logo, LinkedIn provider id), never contacts; their companies: true finds or creates each company in the workspace's companies (by LinkedIn URL, empty fields filled) and links its table row (write scope; allowed without a table). Website-visitor lists write company columns plus domain and visits, each row linked to the workspace's company; never contacts.

    0
  • schedulestring | null

    Refreshing lists are not available yet (422 SCHEDULE_UNAVAILABLE).

    0

Responses

200
The dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
The list run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/lists/post_engagers" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "input": {
    "postUrl": "https://example.com",
    "userPostId": "<userPostId>",
    "kinds": [
      "comments",
      "reactions"
    ]
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

actions.lists.website_visitors

A list of the companies that visited the website.

post/api/v1/actions/lists/website_visitors
Scope
read
Credits
See the catalog entry
Idempotency-Key
required
Class
read
Approval floor
none
Runs
Async
Targets
none
Max targets
100
Dry run
Supported
Max duration
7200 s

The companies Snitcher identified on the workspace's website since since (an ISO date within the last 90 days; default 30 days ago), with their visits, most visits first, those with at least minVisits, at most maxResults (read from the workspace's most recent 2,000 sessions). Needs Snitcher set up (else 422 LIST_SOURCE_UNSUPPORTED). Read class, free: the visits are the workspace's own data; nothing is held or charged. Async only (202 {data: {action}}); one target per page of 25. The companies land in the list's items and, with output.table, in a table (name, LinkedIn URL, industry, location, employees, logo, LinkedIn provider id, domain, visits), each row linked to the workspace's company; never contacts. dryRun: true returns the companies' count and the pages.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

ListsWebsiteVisitorsRequest

  • 0
  • Lists make their own targets (one per provider page).

    0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose connected LinkedIn account runs the search (sources read through your LinkedIn account only). A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); an unbound key must name one (422 IDENTITY_REQUIRED); a session defaults to the member's own.

    0
  • maxCreditsnumber

    Caps the list's credits (default and ceiling the plan's estimatedMax).

    min 0
  • Where the people land besides the list's items. table writes one row per person into a table of this workspace (not available yet for some workspaces: 409 TABLE_STORE_UNSUPPORTED): {tableId} uses its columns that match (key, else name, with a type that takes the value; the plan lists the fields left unmapped), {create: {name}} makes a table with every list column (first name, last name, title, company, location, LinkedIn URL, Sales Navigator URL, profile picture, LinkedIn provider id). Rows are matched by the person (a re-run fills empty cells, never duplicates). contacts: true pushes the rows to contacts (the table push, fill empty fields) when the list finishes; it needs table and the push rule (owner, admin or leader), checked again when the list finishes. Any output needs the write scope as well as enrich (403 INSUFFICIENT_SCOPE). The push outcome (pushed, refused and failed rows, last error code) is on the action's result.contactsPush. Company lists (lists.companies) write company columns instead (name, LinkedIn URL, industry, location, employees, followers, description, logo, LinkedIn provider id), never contacts; their companies: true finds or creates each company in the workspace's companies (by LinkedIn URL, empty fields filled) and links its table row (write scope; allowed without a table). Website-visitor lists write company columns plus domain and visits, each row linked to the workspace's company; never contacts.

    0
  • schedulestring | null

    Refreshing lists are not available yet (422 SCHEDULE_UNAVAILABLE).

    0

Responses

200
The dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
The list run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/lists/website_visitors" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "input": {
    "since": "2026-10-24T09:00:00Z",
    "minVisits": 1,
    "maxResults": 100
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

actions.lists.create

Build a list from any list source.

post/api/v1/actions/lists/create
Scope
enrich
Credits
12 credits per call + 3 credits per record (quantity from input.source.maxResults)
Idempotency-Key
required
Class
spend
Approval floor
none
Runs
Async
Targets
none
Max targets
100
Dry run
Supported
Writes back
contact
Max duration
7200 s

The umbrella of actions.lists.*: input.source.kind names the operation (sales_nav, linkedin_search, icp, companies, company_employees, decision_makers, post_engagers, website_visitors) and the rest of source is its input. Both spellings create the same action (its kind is the source's operation). Spend class, async only (202 {data: {action}}, Location: /api/v1/actions/{id}); target none (the list makes its own targets: one per provider page, run in order). Price audience.scrape.start: 12 per list plus 3 per person written, charged per page once the page is written (a person already written by an earlier page of the same list is not charged again; a page that writes nobody is free), held per batch of pages, never above maxCredits (pages that would pass it are skipped RUN_CAPPED) or the key's daily credit cap (CAP_EXCEEDED). dryRun: true counts the search once with the provider (reused for 15 minutes, also by the call that applies the plan) and returns the pages and the credit estimate; nothing is held or written. The people land in the list's items (read by the list-to-table writer) and, for an audience, in its contacts. Cancel stops at the next page.

Parameters

  • Idempotency-Keyheaderstring

    1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says x-owlbound-idempotent: required (missing: 400 VALIDATION_ERROR, param: Idempotency-Key). Same key and body after completion: the stored response is replayed with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After. Same key, other body or operation: 422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • Owlbound-Dry-Runheaderboolean

    true: same as body field dryRun: true (action operations).

  • Owlbound-Planheaderstring

    A planId from a dry run: same as the body field planId (action operations). A different body planId is 400.

    pattern ^plan_[0-9a-f]{48}$

Request body (required) · application/json

ListsCreateRequest

  • inputListsCreateInputrequired
    0
  • Lists make their own targets (one per provider page).

    0
  • dryRunboolean

    Same as the Owlbound-Dry-Run header.

    0
  • planIdstring

    Apply this dry run's plan (same as Owlbound-Plan). Not with dryRun: true.

    pattern ^plan_[0-9a-f]{48}$
  • modestring

    auto (default) runs inline when the operation is sync, one target would run and the class is not send; sync forces inline (422 ACTION_NOT_SYNC when it cannot); async forces a run.

    autosyncasync
  • Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

    0
  • identityIdstring | null

    The identity whose connected LinkedIn account runs the search (sources read through your LinkedIn account only). A bound key uses its identity (another is 403 IDENTITY_NOT_ALLOWED); an unbound key must name one (422 IDENTITY_REQUIRED); a session defaults to the member's own.

    0
  • maxCreditsnumber

    Caps the list's credits (default and ceiling the plan's estimatedMax).

    min 0
  • Where the people land besides the list's items. table writes one row per person into a table of this workspace (not available yet for some workspaces: 409 TABLE_STORE_UNSUPPORTED): {tableId} uses its columns that match (key, else name, with a type that takes the value; the plan lists the fields left unmapped), {create: {name}} makes a table with every list column (first name, last name, title, company, location, LinkedIn URL, Sales Navigator URL, profile picture, LinkedIn provider id). Rows are matched by the person (a re-run fills empty cells, never duplicates). contacts: true pushes the rows to contacts (the table push, fill empty fields) when the list finishes; it needs table and the push rule (owner, admin or leader), checked again when the list finishes. Any output needs the write scope as well as enrich (403 INSUFFICIENT_SCOPE). The push outcome (pushed, refused and failed rows, last error code) is on the action's result.contactsPush. Company lists (lists.companies) write company columns instead (name, LinkedIn URL, industry, location, employees, followers, description, logo, LinkedIn provider id), never contacts; their companies: true finds or creates each company in the workspace's companies (by LinkedIn URL, empty fields filled) and links its table row (write scope; allowed without a table). Website-visitor lists write company columns plus domain and visits, each row linked to the workspace's company; never contacts.

    0
  • schedulestring | null

    Refreshing lists are not available yet (422 SCHEDULE_UNAVAILABLE).

    0

Responses

200
The dry-run plan.
Show schema

ActionRunResponse

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
202
The list run was created (queued); poll it or read the event feed.
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

Errors

400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still running; `Retry-After` is the lease left, at most 60 s) or IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to store; `details.originalRequestId`). · 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.

curl -X POST "https://app.owlbound.ai/api/v1/actions/lists/create" \
  -H "Authorization: Bearer $OWLBOUND_API_KEY" \
  -H "Owlbound-Version: 2026-10-06" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "input": {
    "source": {
      "url": "https://example.com",
      "kind": "sales_nav"
    }
  },
  "dryRun": true
}'

The example is a dry run: it returns a plan and runs, writes and charges nothing. See dry runs and plans.

Models on this page

Shared objects the operations above link to. Clients must ignore fields they do not know.

ActionTargetContactobject
  • kind"contact"required
    0
  • contactIdstringrequired
    0
ActionTargetContactsobject
  • kind"contacts"required
    0
  • contactIdsarray of stringrequired

    Deduplicated, order kept.

    min items 1max items 1000
ActionTargetLinkedInRecordsobject
  • kind"records"required
    0
  • recordsarray of LinkedInUrlRecordrequired
    min items 1max items 100
LinkedInUrlRecordobject
  • linkedinUrlstringrequired
    max length 500
FindProviderIdInputobject

No options; the LinkedIn URL comes from each target.

ActionNotifyobject

Events for this action. targetEvents: true also writes one action.target.completed / action.target.failed event per target (feed and webhooks); without it only action-level events are written, to keep the volume down. webhook is accepted and has no effect (webhook endpoints subscribe by event type).

  • targetEventsboolean
    default false
  • webhookboolean
    0
Actionobject

One action run. Read it again with GET /api/v1/actions/{id}.

  • idstringrequired
    0
  • kindstringrequired

    The operation id.

    0
  • classstringrequired

    Safety class: decides scope, approval, caps and enforcement.

    readwritespendexternal_writesend
  • statusstringrequired
    pending_approvalqueuedrunningsucceededfailedrejectedcanceledexpiredpartial
  • identityIdstring | nullrequired
    0
  • approvalActionApproval | nullrequired
    0
  • costobjectrequired
    0
    + Show child fields
    • estimatednumberrequired
      0
    • chargednumberrequired
      0
    • reservationIdstring | nullrequired
      0
  • countsActionCountsrequired
    0
  • targetobjectrequired
    0
    + Show child fields
    • kindstringrequired
      0
    • tableIdstring
      0
    • viewIdstring
      0
    • columnIdstring

      The send column this action runs (tables.rows.push target column).

      0
  • outputobject | nullrequired
    0
  • resultanyrequired

    The single target's result (sync), or null; bulk results are per target.

    0
  • errorActionErrorrequired
    0
  • actorActionActorrequired

    Who started the action. agent is an LLM-driven caller (the in-app agent, MCP) acting for the key or member in onBehalfOf.

    0
  • createdAtnumberrequired
    0
  • updatedAtnumberrequired
    0
ActionApprovalobject
  • modestringrequired
    nonealwaysover_threshold
  • urlstring | nullrequired
    0
  • decidedBystring | nullrequired
    0
  • decidedAtnumber | nullrequired
    0
  • expiresAtnumber | nullrequired
    0
ActionCountsobject
  • totalintegerrequired
    0
  • queuedintegerrequired
    0
  • scheduledintegerrequired
    0
  • runningintegerrequired
    0
  • succeededintegerrequired
    0
  • skippedintegerrequired
    0
  • failedintegerrequired
    0
  • canceledintegerrequired
    0
ActionErrorobject
  • codestringrequired
    0
  • messagestringrequired
    0
ActionActorobject

Who started the action. agent is an LLM-driven caller (the in-app agent, MCP) acting for the key or member in onBehalfOf.

  • kindstringrequired
    apiKeysessionagentjob
  • idstringrequired

    API key id, user id, agent run id or job id.

    0
  • onBehalfOfobject

    Agent only.

    0
    + Show child fields
    • kindstringrequired
      apiKeysession
    • idstringrequired
      0
Planobject

What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its planId with the real call to run exactly what was reviewed (409 PLAN_STALE with a new plan if anything bound changed or it expired).

  • operationIdstringrequired
    0
  • classstringrequired

    Safety class: decides scope, approval, caps and enforcement.

    readwritespendexternal_writesend
  • identityIdstring | nullrequired
    0
  • targetsobjectrequired
    0
    + Show child fields
    • totalintegerrequired
      0
    • wouldRunintegerrequired
      0
    • wouldSkiparray of objectrequired
      0
      + Show child fields
      • reasonstringrequired
        0
      • countintegerrequired
        0
      • samplearray of stringrequired
        0
  • creditsobjectrequired
    0
    + Show child fields
    • estimatedMinnumberrequired
      0
    • estimatedMaxnumberrequired
      0
    • availablenumberrequired
      0
    • capRemainingnumber | nullrequired
      0
  • quotaobject | nullrequired

    LinkedIn sends: the daily budget the action spends (an estimate: warm-up, health and the identity's other sends move it; the send gate decides at send time). bucket is the daily limit's key, identityRemainingToday what the identity's account has left today, keyRemainingToday the key's, user's or agent's daily sends left (null: uncapped), wouldDefer the targets that would wait for a later day, firstSlotAt / lastSlotAt when the first and last of them would go (ms; null past 7 days). Null for other operations.

    0
    + Show child fields
    • bucketstringrequired
      0
    • identityRemainingTodaynumberrequired
      0
    • keyRemainingTodaynumber | nullrequired
      0
    • wouldDefernumberrequired
      0
    • firstSlotAtnumber | nullrequired
      0
    • lastSlotAtnumber | nullrequired
      0
  • approvalobjectrequired
    0
    + Show child fields
    • requiredbooleanrequired
      0
    • reasonstring | nullrequired
      key_modeoperation_floorover_thresholdagentrequestedidentity_owner
  • writesobjectrequired
    0
  • previewarray of anyrequired

    The first targets that would run (at most 5).

    0
  • planIdstringrequired

    Valid until expiresAt, for the principal that made the dry run only.

    pattern ^plan_[0-9a-f]{48}$
  • expiresAtnumberrequired

    When the plan expires (epoch milliseconds).

    0
ResponseMetaobject

Metadata on every success response.

  • requestIdstringrequired
    0
  • creditsCreditsMetarequired
    0
  • Cursor pagination. hasMore is the only end signal; pages may be short.

    0
  • dryRunboolean

    True only on a dry-run response (action operations).

    0
CreditsMetaobject
  • usednumberrequired

    Credits charged by this request. Reads are free.

    0
  • balancenumber
    0
  • estimatednumber

    Dry run only (action operations).

    0
  • availablenumber

    Dry run only (action operations).

    0
  • reservationIdstring | null

    Async operations only; the job settles this reservation.

    0
PageMetaobject

Cursor pagination. hasMore is the only end signal; pages may be short.

  • nextCursorstring | nullrequired
    0
  • hasMorebooleanrequired
    0
  • limitintegerrequired
    min 1max 200
ActionTargetPersonRecordsobject
  • kind"records"required
    0
  • recordsarray of PersonRecordrequired
    min items 1max items 100
PersonRecordobject

A person to find; needs firstName and lastName, or email.

  • firstNamestring
    max length 200
  • lastNamestring
    max length 200
  • companystring
    max length 200
  • domainstring

    The company's domain (used to match the workspace's own contacts).

    max length 200
  • emailstring
    max length 320
FindLinkedInUrlInputobject
  • providersarray of LinkedInUrlProvider

    The waterfall, in order (default internal, apollo, zoominfo, linkedin_search). Apollo and ZoomInfo run only with the workspace's own connected keys.

    internalapollozoominfolinkedin_searchmin items 1max items 4
  • minConfidencestring
    lowmediumhigh
FindLinkedInUrlOutputobject
  • contactstring

    Write the found URL onto a contact target: fillEmpty (default) only when it has none, overwrite always, skip never.

    skipfillEmptyoverwrite
ActionTargetSalesNavRecordsobject
  • kind"records"required
    0
  • recordsarray of SalesNavUrlRecordrequired
    min items 1max items 100
SalesNavUrlRecordobject
  • salesNavUrlstringrequired
    max length 500
FindPublicUrlInputobject

No options; the Sales Navigator URL comes from each target.

ActionTargetCompanyQueryRecordsobject
CompanyQueryRecordobject
  • querystringrequired
    min length 1max length 100
FindCompanyIdsInputobject

No options; the query comes from each record.

ListsSalesNavInputobject
  • urlstringrequired

    A Sales Navigator people search or saved lead list URL.

    max length 4000
  • maxResultsinteger

    People to fetch at most.

    default 100min 1max 1000
ActionTargetNoneobject

Lists make their own targets (one per provider page).

  • kind"none"required
    0
ListOutputobject

Where the people land besides the list's items. table writes one row per person into a table of this workspace (not available yet for some workspaces: 409 TABLE_STORE_UNSUPPORTED): {tableId} uses its columns that match (key, else name, with a type that takes the value; the plan lists the fields left unmapped), {create: {name}} makes a table with every list column (first name, last name, title, company, location, LinkedIn URL, Sales Navigator URL, profile picture, LinkedIn provider id). Rows are matched by the person (a re-run fills empty cells, never duplicates). contacts: true pushes the rows to contacts (the table push, fill empty fields) when the list finishes; it needs table and the push rule (owner, admin or leader), checked again when the list finishes. Any output needs the write scope as well as enrich (403 INSUFFICIENT_SCOPE). The push outcome (pushed, refused and failed rows, last error code) is on the action's result.contactsPush. Company lists (lists.companies) write company columns instead (name, LinkedIn URL, industry, location, employees, followers, description, logo, LinkedIn provider id), never contacts; their companies: true finds or creates each company in the workspace's companies (by LinkedIn URL, empty fields filled) and links its table row (write scope; allowed without a table). Website-visitor lists write company columns plus domain and visits, each row linked to the workspace's company; never contacts.

  • tableone of
    0
    + Show child fields

    One of

    with tableId

    • tableIdstringrequired
      0

    with create

    • createobjectrequired
      0
      + Show child fields
      • namestringrequired
        min length 1max length 200
  • contactsboolean
    0
  • companiesboolean
    0
ListsLinkedInSearchInputobject

At least keywords or one filter.

  • keywordsstring
    0
  • locationIdsarray of string
    0
  • industryIdsarray of string
    0
  • seniorityLevelsarray of string
    0
  • companyHeadcountarray of object
    0
    + Show child fields
    • minnumberrequired
      0
    • maxnumber
      0
  • companyTypesarray of string
    0
  • roleKeywordsarray of string
    0
  • excludeRoleKeywordsarray of string
    0
  • companyIdsarray of string
    0
  • excludeCompanyIdsarray of string
    0
  • apistring
    classicsales_navigatordefault "sales_navigator"
  • maxResultsinteger

    People to fetch at most.

    default 100min 1max 1000
ListsIcpInputobject
  • icpProfileIdstringrequired
    0
  • maxPagesinteger
    default 4min 1max 40
ListsCompaniesInputobject

At least keywords or one filter.

  • keywordsstring
    0
  • locationIdsarray of string
    0
  • industryIdsarray of string
    0
  • companyHeadcountarray of object
    0
    + Show child fields
    • minnumberrequired
      0
    • maxnumber
      0
  • apistring
    classicsales_navigatordefault "sales_navigator"
  • maxResultsinteger

    People to fetch at most.

    default 100min 1max 1000
ListsCompanyEmployeesInputobject
  • companyListsCompanyRefrequired

    Exactly one of the company's LinkedIn numeric id, its domain (example.com) or its LinkedIn company URL (https://www.linkedin.com/company/<slug>/).

    0
  • limitinteger
    default 100min 1max 100
ListsCompanyRefobject

Exactly one of the company's LinkedIn numeric id, its domain (example.com) or its LinkedIn company URL (https://www.linkedin.com/company/<slug>/).

  • linkedinIdstring
    pattern ^[1-9][0-9]{0,19}$
  • domainstring
    max length 253
  • urlstring
    max length 2000
ListsDecisionMakersInputobject
  • companyListsCompanyRefrequired

    Exactly one of the company's LinkedIn numeric id, its domain (example.com) or its LinkedIn company URL (https://www.linkedin.com/company/<slug>/).

    0
  • titleKeywordsarray of string
    max items 30
  • limitinteger
    default 50min 1max 50
ListsPostEngagersInputobject

Exactly one of postUrl or userPostId.

  • postUrlstring

    A LinkedIn post URL or its urn:li:activity|ugcPost|share: id.

    max length 2000
  • userPostIdstring

    One of the workspace's posts published through Owlbound.

    0
  • kindsarray of string
    commentsreactionsdefault ["comments","reactions"]
  • maxResultsinteger
    default 200min 1max 200
ListsWebsiteVisitorsInputobject
  • sincestring

    Visits since this time (within the last 90 days; default 30 days ago).

    format: date-time
  • minVisitsinteger
    default 1min 1max 1000
  • maxResultsinteger
    default 100min 1max 1000
ListsCreateInputobject
  • sourceone ofrequired

    kind plus the input of actions.lists.<kind> (sales_nav: ListsSalesNavInput, linkedin_search: ListsLinkedInSearchInput, icp: ListsIcpInput, companies: ListsCompaniesInput, company_employees: ListsCompanyEmployeesInput, decision_makers: ListsDecisionMakersInput, post_engagers: ListsPostEngagersInput, website_visitors: ListsWebsiteVisitorsInput).

    0
    + Show child fields

    One of

    kind: "sales_nav"

    • urlstringrequired

      A Sales Navigator people search or saved lead list URL.

      max length 4000
    • maxResultsinteger

      People to fetch at most.

      default 100min 1max 1000
    • kind"sales_nav"required
      0

    kind: "linkedin_search"

    • kind"linkedin_search"required
      0

    kind: "icp"

    • kind"icp"required
      0

    kind: "companies"

    • kind"companies"required
      0

    kind: "company_employees"

    • kind"company_employees"required
      0

    kind: "decision_makers"

    • kind"decision_makers"required
      0

    kind: "post_engagers"

    • kind"post_engagers"required
      0

    kind: "website_visitors"

    • kind"website_visitors"required
      0

← All operations