# RecruitMCP API Base https://api.recruitmcp.com. MCP https://mcp.recruitmcp.com/mcp. Version 2026-10-13. Idempotency-Key is required unless dry_run=true. Common errors (unsupported_version, unauthorized, insufficient_scope, forbidden, rate_limited) apply to every authenticated call and are omitted below. ## POST /v1/workspaces Create a workspace Returns the first API key once. When email verification is on, signup credits are added after the email link is opened. attribution is optional. When it is omitted, the rmcp_attr cookie from the first visit is stored instead. marketing_opt_in is optional and defaults to false. Cost: Free. Scopes: none Errors: 400 invalid_request ## POST /v1/signup Create a workspace Same as POST /v1/workspaces. attribution is optional. When it is omitted, the rmcp_attr cookie from the first visit is stored instead. Cost: Free. Scopes: none Errors: 400 invalid_request ## POST /v1/workspaces/verify Confirm a signup email No authentication. Cost: Free. Scopes: none Errors: 400 invalid_request ## GET /v1/workspace Get the current workspace and key Scope: `account:read`. Cost: Free. Scopes: account:read ## PATCH /v1/workspace Update workspace preferences credits.low fires when the balance drops below low_balance_credits. The default is 250. Send null to restore the default. marketing_opt_in stores the product-updates choice. lifecycle_suppressed stops follow-up emails. Send at least one of these fields. Cost: Free. Scopes: account:manage Errors: 400 invalid_request ## GET /v1/api-keys List API keys Scope: `account:read`. Acts on the account; keys bound to a customer are refused. Cost: Free. Scopes: account:read Errors: 400 invalid_request ## POST /v1/api-keys Create an API key A key never gets more scopes, a higher daily cap, or a higher approval threshold than the key that creates it. Omitted scopes copy the caller except outreach:approve, which a new key gets only when the request lists it. A key with account:manage may grant outreach:approve. A recommended agent key is sourcing:read, sourcing:spend, lists:write, contacts:spend, outreach:read, outreach:write, and outreach:send. Add outreach:approve only to approve, reject, or turn approve_every_message off. Do not put account:manage or billing:manage on an agent key. Raising an outreach cap above its default needs account:manage. Set customer_id to bind the key to one customer. approval_threshold_credits null or omitted means no HTTP threshold and 500 credits on MCP. approval_threshold_enrollments null or omitted means no HTTP threshold and 25 scheduled enrollments on MCP. The key pins the RecruitMCP-Version sent with this request, or the current version. Cost: Free. Scopes: account:manage Errors: 400 invalid_request ## DELETE /v1/api-keys/{key_id} Revoke an API key Runs and jobs started with the key stop at their next step. Cost: Free. Scopes: account:manage Errors: 400 invalid_request, 404 not_found ## GET /v1/media/{token} Get a profile photo Public. The token in a profile photo field expires after 7 days, and each API response signs a new one. It is not tied to a workspace and does not contain the original address. Requests are limited per network. The image is cached on this server and the response is private for one day. Erasure and a confirmed opt-out delete that person's cached photo; every token for them then returns 404. Cost: Free. Scopes: none Errors: 400 invalid_request, 404 not_found, 502 upstream_error ## GET /v1/customers List customers Customers are sub-workspaces for platforms that serve their own clients. Each has its own seen register, lists, suppressions, outreach accounts, and daily cap; credits come from your account. Cost: Free. Scopes: account:read Errors: 400 invalid_request ## POST /v1/customers Create a customer Select it on any request with the RecruitMCP-Customer header, or create a key bound to it. Cost: Free. Scopes: account:manage Errors: 400 invalid_request, 409 conflict ## GET /v1/customers/{customer_id} Get a customer Scope: `account:read`. Acts on the account; keys bound to a customer are refused. Cost: Free. Scopes: account:read Errors: 400 invalid_request, 404 not_found ## PATCH /v1/customers/{customer_id} Update a customer A disabled customer refuses every request and its runs stop at their next step. Cost: Free. Scopes: account:manage Errors: 400 invalid_request, 404 not_found ## DELETE /v1/customers/{customer_id} Delete a customer and its data Revokes its bound keys and deletes its seen register, lists, caches, and outreach data. Spend stays on your ledger. Cost: Free. Scopes: account:manage Errors: 400 invalid_request, 404 not_found ## GET /v1/billing/plans List plans and credit rules No authentication. Cost: Free. Scopes: none ## GET /v1/billing/balance Get the credit balance Account balance by source. A customer-bound key receives that customer's remaining daily cap, or null when the customer has no cap. It does not receive the account pool, buckets, or subscription. Cost: Free. Scopes: account:read ## GET /v1/usage Get credit usage A customer-bound key or a RecruitMCP-Customer header sees only that customer's spend. A bound key's balance is its remaining daily cap, or null when the customer has no cap. An account key still sees the account balance. Cost: Free. Scopes: account:read Errors: 400 invalid_request ## POST /v1/billing/checkout Start a credit pack checkout The only pack is topup: €99 for 7,500 credits. Checkout saves the card for off-session auto-refill. Removed pack ids return 400. Cost: Free. Scopes: billing:manage Errors: 400 invalid_request ## POST /v1/billing/subscriptions Start a subscription checkout Scope: `billing:manage`. Acts on the account; keys bound to a customer are refused. Cost: Free. Scopes: billing:manage Errors: 400 invalid_request, 409 conflict ## POST /v1/billing/subscription/plan Change the subscription plan Scope: `billing:manage`. Acts on the account; keys bound to a customer are refused. Cost: Free. Scopes: billing:manage Errors: 400 invalid_request, 409 conflict ## GET /v1/billing/auto-refill Get auto-refill Threshold, monthly caps, whether a card is on file, and how many refills have been granted this UTC month. Account keys only. Cost: Free. Scopes: account:read ## PUT /v1/billing/auto-refill Enable or update auto-refill When the balance is below threshold_credits, the worker charges the €99 pack off-session, up to the monthly caps. A card must already be on file from a pack checkout. Credits are granted only after the payment succeeds. Account keys only. Cost: Free. Scopes: billing:manage Errors: 400 invalid_request, 409 conflict ## DELETE /v1/billing/auto-refill Turn auto-refill off Keeps the saved card and the last threshold. Account keys only. Cost: Free. Scopes: billing:manage ## GET /v1/billing/developer Get Developer billing Spending limit and current-period metered usage. 404 feature_disabled when Developer billing is off for this deployment. Account keys only. Cost: Free. Scopes: account:read Errors: 404 feature_disabled, 409 conflict ## PATCH /v1/billing/developer Set the Developer spending limit Whole euros from 10 to 1000. The first unpaid cycle is also capped, and a server ceiling can be lower. 404 feature_disabled when Developer billing is off. Account keys only. Cost: Free. Scopes: billing:manage Errors: 400 invalid_request, 404 feature_disabled, 409 conflict ## POST /v1/billing/developer/checkout Start Developer card setup Stripe Checkout in setup mode saves a card. Usage after the prepaid balance is zero is metered and billed monthly in arrears. Refused while a plan subscription is open. 404 feature_disabled when Developer billing is off. Account keys only. Cost: Free. Scopes: billing:manage Errors: 404 feature_disabled, 409 conflict, 503 internal ## GET /v1/billing/transactions List credit transactions Credit grants, purchases, usage, and expiries, newest first. A customer-bound key sees the account ledger. Upstream cost rows are omitted. kind filters to grant, purchase, usage, or expiry. description says what the row is. A profile enrich that did not finish or found nothing is returned as a positive grant with a description that the credits were returned. Cost: Free. Scopes: account:read Errors: 400 invalid_request ## GET /v1/lookups/locations Find location ids Turns a place name into geo_ids for people search filters. Free, including a place this server has not seen before. The result is cached. This call never charges. An empty result includes a hint. A region name points at a city or the country. Cost: Free. A place this server has not seen before is looked up and cached, and this call never charges. Scopes: sourcing:read Errors: 400 invalid_request, 402 free_tier_limit, 429 upstream_busy, 502 upstream_busy, 502 upstream_error, 503 upstream_busy ## GET /v1/lookups/areas Find the location ids around anchor places Free. Anchor places plus a radius become at most 12 location ids. Under 20 km only the anchor city is used. At 20 km or more, major cities within the radius are included when coordinates are known. geo_ids is that set. The search index has no radius of its own: pass geo_ids into a people search. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request, 402 free_tier_limit, 429 upstream_busy, 502 upstream_busy, 502 upstream_error, 503 upstream_busy ## GET /v1/lookups/industries List industries Industry ids. Use the ids in industry_ids and exclude_industry_ids. Free. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## GET /v1/lookups/seniorities List seniority levels Seniority ids. Use the ids in seniority_level_ids and exclude_seniority_level_ids. Free. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## GET /v1/lookups/experience-ranges List experience ranges Year buckets for total experience and time at the current company. 1 is under a year, 2 is 1 to 2 years, 3 is 3 to 5 years, 4 is 6 to 10 years, 5 is more than 10 years. Use the ids in years_of_experience_ids and years_at_current_company_ids. Free. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## GET /v1/lookups/functions List job functions Job function ids. 8 is Engineering. Use the ids in function_ids and exclude_function_ids. Free. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## GET /v1/lookups/languages List profile languages Languages a profile is written in. Use the ids in profile_languages. Free. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## GET /v1/lookups/headcounts List company size ranges Current employer headcount. A is self-employed, B is 1-10, C is 11-50, D is 51-200, E is 201-500, F is 501-1,000, G is 1,001-5,000, H is 5,001-10,000, I is 10,001+. Use the ids in company_headcount. Free. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## POST /v1/people/search Search people Profiles for a filter set. limit is how many profiles to return, from 1 to 100, and defaults to 25. cursor continues a previous search: send the next_cursor from the last response. Filters map one to one to what the index supports; an unknown or unsupported filter is refused with unsupported_filter, and an unknown body field with invalid_request, never ignored. Cost: Up to limit × 1 credit per profile returned. Default limit is 25. A profile already billed in this workspace is free. An empty result is free. dry_run spends nothing, and its credits_max equals limit. Scopes: sourcing:spend Errors: 400 idempotency_key_required, 400 invalid_request, 400 unsupported_filter, 402 daily_credit_cap_reached, 402 free_tier_limit, 402 insufficient_credits, 409 approval_required, 409 confirm_token_used, 409 idempotency_in_progress, 409 idempotency_key_reused, 429 upstream_busy, 502 upstream_busy, 502 upstream_error, 503 upstream_busy, 504 gateway_timeout ## GET /v1/people/{profile_id} Get a person from your cache Never charges and never calls the person index. Returns 404 not_cached when the person has not been enriched in this workspace within max_age_days; enrich them with POST /v1/people:enrich. profile_id may also be a URL-encoded profile URL. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request, 404 not_cached, 404 suppressed ## DELETE /v1/people/{profile_id} Erase a person from this workspace Deletes the cached profile, contacts, seen entries, and list items for this person in the workspace. Does not suppress them. POST /v1/erasures with suppress true also blocks future results. Cost: Free. Scopes: privacy:write Errors: 400 invalid_request, 404 not_found ## POST /v1/people:enrich Enrich profiles Full public professional profiles for up to 100 profile ids or profile URLs. This does not return email or phone; a contact lookup does that. The body is the full profile, including education. MCP enrich_profiles defaults view to full and returns that same profile; compact is opt-in. Credits stay the profile price either way. profile_id is the search id (often ACw…) or a public profile URL. alternate_id is the other member id for the same person (often ACo…) when both are known. Either id reads the same cached profile. Cached copies younger than max_age_days are free. When everything is cached the profiles come back now (200). Otherwise a job is queued (202) and X-Credits-Charged is 0; the charge happens when the job completes. Poll GET /v1/jobs/{job_id} or wait for job.completed. A suppressed person is omitted and never charged. Cost: 2 credits per live profile that is found. The profile does not include email or phone. Cached profiles, missing profiles, and suppressed people are free. Scopes: sourcing:spend Errors: 400 idempotency_key_required, 400 invalid_request, 402 insufficient_credits, 409 approval_required, 409 confirm_token_used, 409 idempotency_in_progress, 409 idempotency_key_reused ## POST /v1/people:match Find one person by name and current company Looks up one person by name and current company. Charged one lead credit only when exactly one person matches (outcome exact), and only the first time that person is returned. Ambiguous and no-match outcomes are free. Cost: 1 credit when exactly one person matches, the first time only. Ambiguous and no-match results are free. Scopes: sourcing:spend Errors: 400 idempotency_key_required, 400 invalid_request, 402 daily_credit_cap_reached, 402 free_tier_limit, 402 insufficient_credits, 409 approval_required, 409 confirm_token_used, 409 idempotency_in_progress, 409 idempotency_key_reused, 429 upstream_busy, 502 upstream_busy, 502 upstream_error, 503 upstream_busy ## GET /v1/jobs List profile fetch jobs Scope: `sourcing:read`. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## GET /v1/jobs/{job_id} Get a job When the job is completed, result.data holds the profiles. view defaults to full, the same profile enrich returns, including education. view=compact is the short profile. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request, 404 not_found ## GET /v1/lookups/companies Search known companies Searches the built-in company list. Free. For any other name use POST /v1/companies:resolve. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## POST /v1/companies:resolve Resolve company names to company URLs Use the URLs in current_companies or past_companies filters. A cache hit, a company on the built-in list, and a lookup with no result are free. A company found live costs 1 credit, unless the profile source marks that lookup free. Cost: 1 credit when a company is found live, unless the profile source marks that lookup free. A lookup with no result, a cache hit, or a built-in company is free. Scopes: sourcing:spend Errors: 400 idempotency_key_required, 400 invalid_request, 402 daily_credit_cap_reached, 402 insufficient_credits, 409 approval_required, 409 confirm_token_used, 409 idempotency_in_progress, 409 idempotency_key_reused, 429 upstream_busy, 502 upstream_busy, 502 upstream_error, 503 upstream_busy, 504 gateway_timeout ## GET /v1/people/{profile_id}/contacts Get stored contact details Free. Only what an earlier lookup found. Each email includes type work or personal when the lookup provided it. contacts:spend can read contacts it paid for. sourcing:read can read them too. Cost: Free. Reading or deleting a stored contact does not spend credits. Scopes: sourcing:read, contacts:spend Errors: 400 invalid_id, 400 invalid_request, 404 not_found, 503 contacts_unavailable ## POST /v1/people/{profile_id}/contacts Look up email and phone Email and phone, with a confidence score. Each email includes type work or personal when the lookup provides it. Charged only when an email or phone is found; a miss is free. The person must be fetched first. The body is always { data, cost }, including one person and a repeat of a stored lookup. Results may arrive later; a 202 has status pending, canonical_id, job_id, and poll_url for GET /v1/contacts/jobs/{job_id}. contacts.completed is emitted when they are ready. Replaying the Idempotency-Key after completion returns the completed result and does not charge again. That replay reports the original cost.credits and each person's credits, with charged_this_request 0. dry_run in the query or the JSON body previews and never charges, and accepts contacts:spend or sourcing:read. A malformed person id is 400 invalid_id. The reserved id test_miss_0000 always returns not_found, charges 0, and does not call the contact provider. It does not need a fetched profile, and it applies only to contact lookup. Cost: A found contact costs 25 credits. A miss is free. dry_run=true returns the estimate and charges nothing. Scopes: contacts:spend Errors: 400 idempotency_key_required, 400 invalid_id, 400 invalid_request, 402 daily_credit_cap_reached, 402 insufficient_credits, 404 not_found, 404 suppressed, 409 approval_required, 409 confirm_token_used, 409 idempotency_in_progress, 409 idempotency_key_reused, 503 contacts_unavailable, 503 upstream_busy ## DELETE /v1/people/{profile_id}/contacts Delete stored contact details Scope: `privacy:write`. Cost: Free. Reading or deleting a stored contact does not spend credits. Scopes: privacy:write Errors: 400 invalid_id, 400 invalid_request, 404 not_found ## POST /v1/people/contacts:fetch Look up email and phone for many people Email and phone, with a confidence score, for up to 100 fetched people. Each email includes type work or personal when the lookup provides it. Same pricing and the same { data, cost } body as the single lookup, including a repeat of a stored lookup. A 202 includes job_id, poll_url, and canonical_id on each person. Replaying the Idempotency-Key after completion returns the completed result and does not charge again. That replay reports the original cost.credits and each person's credits, with charged_this_request 0. dry_run in the query or the JSON body previews and never charges, and accepts contacts:spend or sourcing:read. A malformed person id is 400 invalid_id. The reserved id test_miss_0000 always returns not_found, charges 0, and does not call the contact provider. It does not need a fetched profile, and it applies only to contact lookup. Cost: A found contact costs 25 credits. A miss is free. dry_run=true returns the estimate and charges nothing. Scopes: contacts:spend Errors: 400 idempotency_key_required, 400 invalid_id, 400 invalid_request, 402 daily_credit_cap_reached, 402 insufficient_credits, 404 not_found, 404 suppressed, 409 approval_required, 409 confirm_token_used, 409 idempotency_in_progress, 409 idempotency_key_reused, 503 contacts_unavailable, 503 upstream_busy ## GET /v1/contacts/jobs/{job_id} Get a contact lookup Free. Poll the job_id from a contact lookup that returned HTTP 202. Requires contacts:spend. status is pending until every person is stored, then completed with the emails and phones. cost.credits and each person's credits are the credits that job charged, read from the ledger, and both are 0 while the job is pending. charged_this_request is 0. This call never charges. Cost: Free. Polling a contact lookup does not spend credits. Scopes: contacts:spend Errors: 400 invalid_request, 404 not_found ## GET /v1/seen List the seen register Everyone this workspace has seen, shortlisted, contacted, or rejected. A people search marks them already_seen, and drops them when exclude_seen is true. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## POST /v1/seen Add or update seen entries Up to 1000 people. An entry matching an existing one (same profile, or same name and employer) is updated. Use external_ids to keep your ATS ids next to each person. Cost: Free. Scopes: lists:write, sourcing:spend Errors: 400 invalid_request ## POST /v1/seen:check Check people against the seen register Up to 1000 identities, each a profile_url, profile_id, or full_name with current_employer. Free. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## GET /v1/seen/{seen_id} Get a seen entry Scope: `sourcing:read`. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request, 404 not_found ## PATCH /v1/seen/{seen_id} Update a seen entry external_ids are merged; tags replace the stored tags. Cost: Free. Scopes: lists:write, sourcing:spend Errors: 400 invalid_request, 404 not_found ## DELETE /v1/seen/{seen_id} Remove a seen entry The person can be returned by a later search. exclude_seen no longer drops them. Cost: Free. Scopes: lists:write, sourcing:spend Errors: 400 invalid_request, 404 not_found ## GET /v1/lists List candidate lists Scope: `sourcing:read`. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## POST /v1/lists Create a candidate list Scope: `lists:write`. A key with `sourcing:spend` is also accepted. Cost: Free. Scopes: lists:write, sourcing:spend Errors: 400 invalid_request, 409 conflict ## GET /v1/lists/{list_id} Get a list Scope: `sourcing:read`. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request, 404 not_found ## PATCH /v1/lists/{list_id} Rename or describe a list Scope: `lists:write`. A key with `sourcing:spend` is also accepted. Cost: Free. Scopes: lists:write, sourcing:spend Errors: 400 invalid_request, 404 not_found, 409 conflict ## DELETE /v1/lists/{list_id} Delete a list Scope: `lists:write`. A key with `sourcing:spend` is also accepted. Cost: Free. Scopes: lists:write, sourcing:spend Errors: 400 invalid_request, 404 not_found ## GET /v1/lists/{list_id}/items List the people on a list Scope: `sourcing:read`. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request, 404 not_found ## POST /v1/lists/{list_id}/items Add people to a list People already on the list are skipped. The search id and the other member id are the same person and are stored once, under the search id. Cost: Free. Scopes: lists:write, sourcing:spend Errors: 400 invalid_request, 404 not_found ## DELETE /v1/lists/{list_id}/items/{item_id} Remove a person from a list Scope: `lists:write`. A key with `sourcing:spend` is also accepted. Cost: Free. Scopes: lists:write, sourcing:spend Errors: 400 invalid_request, 404 not_found ## GET /v1/lists/{list_id}/export Export a list as CSV One row per person. An empty email is filled from a contact lookup that found one. An opted-out address is left blank, and a suppressed person is omitted. The photo column is this API's media URL. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request, 404 not_found ## GET /v1/outreach/settings Get outreach settings Working hours follow this workspace timezone, default Europe/Brussels, Monday to Friday 08:00–19:00 local. The account IP pins the connection country and does not change the window. Nothing is sent outside these hours. lowered_limits.outreaches_started_per_day lowers the per-account daily new-outreach cap. It is not a shared pool. Cost: Free. Scopes: outreach:read ## PATCH /v1/outreach/settings Update outreach settings Workspace caps can only be lowered here. Working hours stay inside the platform window and use the timezone on this object. Turning approve_every_message from true to false requires both outreach:write and outreach:approve. On REST, omitting dry_run is the confirmation. On MCP it is confirm=true. Cost: Free. Scopes: outreach:write Errors: 400 invalid_request ## GET /v1/outreach/templates List sequence templates Scope: `outreach:read`. Cost: Free. Scopes: outreach:read ## POST /v1/outreach/accounts Connect a LinkedIn account Returns a connect_url for the recruiter to sign in. Call it from the recruiter's browser (or pass their IP) so traffic stays in their country. account.connected is emitted when sign-in finishes. Billed per connected account per month. Cost: Free. Scopes: outreach:write Errors: 400 invalid_request, 428 client_ip_required, 503 account_connect_unavailable ## GET /v1/outreach/accounts List outreach accounts Scope: `outreach:read`. Cost: Free. Scopes: outreach:read Errors: 400 invalid_request ## GET /v1/outreach/accounts/{account_id} Get an outreach account Scope: `outreach:read`. Cost: Free. Scopes: outreach:read Errors: 400 invalid_request, 404 not_found ## DELETE /v1/outreach/accounts/{account_id} Disconnect an outreach account Stops every open enrollment on the account, archives its sequences, and removes it. Nothing more is sent from it. Cost: Free. Scopes: outreach:write Errors: 400 invalid_request, 404 not_found ## GET /v1/outreach/accounts/{account_id}/limits Get today's limits for an account What was sent, what is scheduled, and the caps. outreaches_started.scope is account: the daily new-outreach cap counts on this account. workspace_cap is the workspace lowered limit for that same cap, applied to every account, not a shared pool. next_available_without_note_at is the next invite slot that fits the weekly cap for invites without a note. Classic, recruiter, and sales seats share that cap. Manual actions taken in the product outside this API are not copied into these counters. Cost: Free. Scopes: outreach:read Errors: 400 invalid_request, 404 not_found ## PATCH /v1/outreach/accounts/{account_id}/limits Change an account's caps Lowering is always allowed with outreach:write. Raising above a default requires account:manage, plus risk_acknowledged true, and is recorded. Workspace settings may only lower caps. Cost: Free. Scopes: outreach:write Errors: 400 invalid_request, 404 not_found ## GET /v1/outreach/sequences List sequences Scope: `outreach:read`. Cost: Free. Scopes: outreach:read Errors: 400 invalid_request ## POST /v1/outreach/sequences Create a sequence Steps from a template or your own. account_id is optional: omit it to save an accountless draft. Creating a sequence sends nothing. A dry_run enrollment preview works on a draft. Enrolling or sending needs a connected account. Cost: Free. Scopes: outreach:write Errors: 400 invalid_request, 409 conflict ## GET /v1/outreach/sequences/{sequence_id} Get a sequence Scope: `outreach:read`. Cost: Free. Scopes: outreach:read Errors: 400 invalid_request, 404 not_found ## PATCH /v1/outreach/sequences/{sequence_id} Update a sequence New steps apply to enrollments that have not reached them yet. account_id and template cannot be changed; unknown fields are refused. Turning approve_every_message from true to false requires both outreach:write and outreach:approve. Cost: Free. Scopes: outreach:write Errors: 400 invalid_request, 404 not_found ## DELETE /v1/outreach/sequences/{sequence_id} Delete a sequence Refused with 409 while it has open enrollments; stop them or archive the sequence. Cost: Free. Scopes: outreach:write Errors: 400 invalid_request, 404 not_found, 409 conflict ## GET /v1/outreach/enrollments List enrollments Scope: `outreach:read`. Cost: Free. Scopes: outreach:read Errors: 400 invalid_request ## POST /v1/outreach/enrollments Enroll people in a sequence People from candidates, a list (list_id), or fetched profiles (profile_ids), de-duplicated. Up to 500. On REST, omitting dry_run is the confirmation. On MCP it is confirm=true. The scope is outreach:send. Cost: No credits. A connected outreach account is €49 per month. Scopes: outreach:send Errors: 400 idempotency_key_required, 400 invalid_request, 404 not_found, 409 account_not_ready, 409 account_paused, 409 confirm_token_used, 409 conflict, 409 idempotency_in_progress, 409 idempotency_key_reused ## GET /v1/outreach/enrollments/{enrollment_id} Get an enrollment Scope: `outreach:read`. Cost: Free. Scopes: outreach:read Errors: 400 invalid_request, 404 not_found ## POST /v1/outreach/enrollments/{enrollment_id}/pause Pause an enrollment Scope: `outreach:write`. Cost: Free. Scopes: outreach:write Errors: 400 invalid_request, 404 not_found ## POST /v1/outreach/enrollments/{enrollment_id}/resume Resume an enrollment ?dry_run=true shows when the next step would go out. On REST, omitting dry_run is the confirmation. On MCP it is confirm=true. Cost: No credits. A connected outreach account is €49 per month. Scopes: outreach:send Errors: 400 idempotency_key_required, 400 invalid_request, 404 not_found, 409 account_not_ready, 409 account_paused, 409 conflict, 409 idempotency_in_progress, 409 idempotency_key_reused ## POST /v1/outreach/enrollments/{enrollment_id}/stop Stop an enrollment Final. Nothing more is sent to this person from this enrollment. Cost: Free. Scopes: outreach:write Errors: 400 invalid_request, 404 not_found ## GET /v1/outreach/actions List outreach actions Every scheduled, sent, failed, or held step. outcome=awaiting_approval lists messages waiting for approval. Cost: Free. Scopes: outreach:read Errors: 400 invalid_request ## GET /v1/outreach/actions/{action_id} Get an outreach action Scope: `outreach:read`. Cost: Free. Scopes: outreach:read Errors: 400 invalid_request, 404 not_found ## POST /v1/outreach/actions/{action_id}/approve Approve a held message Scope outreach:approve. On REST, omitting dry_run is the confirmation. On MCP it is confirm=true. ?dry_run=true returns the rendered message and changes nothing. Optional body or note replaces the rendered text for this person only. A held message expires after 7 days: the action outcome becomes expired and the enrollment pauses, so later steps do not send until it is resumed. Cost: No credits. A connected outreach account is €49 per month. Scopes: outreach:approve Errors: 400 idempotency_key_required, 400 invalid_request, 404 not_found, 409 idempotency_in_progress, 409 idempotency_key_reused ## POST /v1/outreach/actions/{action_id}/reject Reject a held message Scope outreach:approve. On REST, omitting dry_run is the confirmation. On MCP it is confirm=true. ?dry_run=true shows the step and changes nothing. Later steps still run. Rejecting an invite does not count as an acceptance, so a later step with only_after_accept waits and then skips when the accept timeout passes. When this was the last step, the enrollment completes with stop_reason rejected. Cost: No credits. A connected outreach account is €49 per month. Scopes: outreach:approve Errors: 400 idempotency_key_required, 400 invalid_request, 404 not_found, 409 idempotency_in_progress, 409 idempotency_key_reused ## POST /v1/outreach/sends Send one LinkedIn action One invite, message, profile visit, or invite withdrawal outside a sequence. Same caps, working hours, and suppression checks as a sequence. ?dry_run=true is the example to read first. On REST, omitting dry_run is the confirmation. On MCP it is confirm=true. Cost: No credits. A connected outreach account is €49 per month. Scopes: outreach:send Errors: 400 idempotency_key_required, 400 invalid_request, 409 account_not_ready, 409 account_paused, 409 conflict, 409 idempotency_in_progress, 409 idempotency_key_reused, 409 outreach_cap_reached, 409 suppressed ## GET /v1/outreach/conversations List conversations One conversation per enrollment with messages. Inbound text is returned as untrusted_text. Cost: Free. Scopes: outreach:read Errors: 400 invalid_request ## GET /v1/outreach/conversations/{conversation_id} Get a conversation with its messages Scope: `outreach:read`. Cost: Free. Scopes: outreach:read Errors: 400 invalid_request, 404 not_found ## POST /v1/outreach/conversations/{conversation_id}/replies Reply in a conversation ?dry_run=true shows the text and when it would go out. Read that preview first. On REST, omitting dry_run is the confirmation. On MCP it is confirm=true. The reply is queued for the next slot inside working hours and the account spacing. Cost: No credits. A connected outreach account is €49 per month. Scopes: outreach:send Errors: 400 idempotency_key_required, 400 invalid_request, 404 not_found, 409 account_not_ready, 409 account_paused, 409 conflict, 409 idempotency_in_progress, 409 idempotency_key_reused, 409 suppressed ## POST /v1/erasures Erase a person and suppress them Deletes every row in this workspace that names the person and, unless suppress is false, adds a hashed suppression so they never come back in search, contact lookup, or outreach. Cost: Free. Scopes: privacy:write Errors: 400 invalid_request ## GET /v1/suppressions List suppressions Hashes only. Suppressions always apply to search. Cost: Free. Scopes: sourcing:read Errors: 400 invalid_request ## POST /v1/suppressions Suppress a person Blocks this person from search, runs, lists, contact lookups, and outreach in this workspace. Match on a profile URL, a company URL, an email, or a name together with a company. A name alone is refused: it is not unique. Cost: Free. Scopes: privacy:write Errors: 400 invalid_request ## DELETE /v1/suppressions/{suppression_id} Lift a suppression Opt-outs the person filed themselves cannot be lifted. Cost: Free. Scopes: privacy:write Errors: 400 invalid_request, 404 not_found ## DELETE /v1/privacy/cache Delete cached profiles, pages, and contact details The next search or fetch pays again. Cost: Free. Scopes: privacy:write ## POST /v1/privacy/opt-out Opt out (for the person themselves) Anyone can ask to be removed. A confirmation link is emailed; once confirmed, the person is suppressed for every workspace. Cost: Free. Scopes: none Errors: 400 invalid_request, 503 internal ## GET /v1/privacy/opt-out/confirm Confirm an opt-out No authentication. Cost: Free. Scopes: none Errors: 400 invalid_request, 503 internal ## GET /v1/events List events Everything that happened on the account in the last 30 days: jobs, contact lookups, enrollments, replies, accounts, and credits. A customer key sees only its customer's events. The same events are pushed to webhook endpoints. Cost: Free. Scopes: account:read Errors: 400 invalid_request ## GET /v1/events/{event_id} Get an event Scope: `account:read`. Cost: Free. Scopes: account:read Errors: 400 invalid_request, 404 not_found ## GET /v1/webhook-endpoints List webhook endpoints Scope: `account:read`. Acts on the account; keys bound to a customer are refused. Cost: Free. Scopes: account:read Errors: 400 invalid_request ## POST /v1/webhook-endpoints Add a webhook endpoint Up to 10 per account. The URL must be public https; private, loopback, and link-local addresses are refused, the address is checked again on every delivery, and redirects are not followed. Each delivery is a POST with the event as JSON and a X-RecruitMCP-Signature header: t=,v1=." with the endpoint secret>. Reject a delivery whose t is more than five minutes old. Failed deliveries are retried with backoff for about a day; use the event id to ignore duplicates. Cost: Free. Scopes: account:manage Errors: 400 invalid_request, 409 conflict ## GET /v1/webhook-endpoints/{endpoint_id} Get a webhook endpoint Scope: `account:read`. Acts on the account; keys bound to a customer are refused. Cost: Free. Scopes: account:read Errors: 400 invalid_request, 404 not_found ## PATCH /v1/webhook-endpoints/{endpoint_id} Update a webhook endpoint Scope: `account:manage`. Acts on the account; keys bound to a customer are refused. Cost: Free. Scopes: account:manage Errors: 400 invalid_request, 404 not_found ## DELETE /v1/webhook-endpoints/{endpoint_id} Delete a webhook endpoint Scope: `account:manage`. Acts on the account; keys bound to a customer are refused. Cost: Free. Scopes: account:manage Errors: 400 invalid_request, 404 not_found ## POST /v1/webhook-endpoints/{endpoint_id}/rotate-secret Rotate an endpoint's signing secret The old secret stops working immediately. Cost: Free. Scopes: account:manage Errors: 400 invalid_request, 404 not_found ## POST /v1/webhook-endpoints/{endpoint_id}/test Send a test event Sends one signed ping event now and reports the answer. Not retried. Cost: Free. Scopes: account:manage Errors: 400 invalid_request, 404 not_found