CVPitch API, webhooks and MCP for developers

CVPitch developer docs: REST API, API keys and OAuth 2.1 with PKCE, scopes, endpoints, upload formats, signed webhooks, REST hooks and the MCP server.

The CVPitch API, together with signed webhooks and a remote MCP server, lets you connect candidate submission formatting to your ATS, CRM, automation platform or AI assistant. This page is an overview for developers and technical operations staff. For a non-technical summary, see integrations and the full list of features.

The design rule behind every interface: integrations can read metadata, upload CVs, request previews and export submissions a human has already approved, but nothing outside the CVPitch app can approve a submission.

Overview

ItemValue
REST base URLhttps://cvpitch.app/integrations/v1
MCP endpointhttps://cvpitch.app/mcp
Authorisation server metadatahttps://cvpitch.app/.well-known/oauth-authorization-server
Protected resource metadatahttps://cvpitch.app/.well-known/oauth-protected-resource (REST) and .../oauth-protected-resource/mcp (MCP)
OpenAPI documenthttps://cvpitch.app/integrations/v1/openapi.json (OpenAPI 3.1, public)
FormatJSON, except document upload (multipart) and file download
AuthenticationAuthorization: Bearer YOUR_TOKEN with an API key or OAuth access token

Browser session cookies do not authorise the API. Requests with an Origin header from an untrusted origin are refused.

Authentication

API keys

A workspace owner creates API keys in CVPitch and chooses their scopes. A key is shown once, stored hashed and can be revoked at any time. Treat it like a password: keep it in a secrets manager, never in a URL or a chat message. Each key acts on behalf of the member who created it, so access ends if that membership is removed.

OAuth 2.1 with PKCE

Third-party applications and AI assistants use the authorisation code flow with PKCE:

  1. Discover the endpoints from the authorisation server metadata.
  2. Send the user to /oauth/authorize with response_type=code, your client_id, an exact registered redirect_uri, the requested scope, a state value, a code_challenge with code_challenge_method=S256, and a resource parameter set to the REST base URL or the MCP endpoint.
  3. The user signs in to CVPitch and sees a consent screen naming the workspace and the permissions requested.
  4. Exchange the code at /oauth/token as a form post with grant_type=authorization_code, the code, your client_id, the same redirect_uri and resource, and your code_verifier. Codes are single-use and expire quickly.
  5. Use the access token as a bearer token. Tokens are short-lived and bound to one audience: a token issued for the REST API does not work on the MCP endpoint, and the reverse.

Only S256 is supported for PKCE, and public clients do not use a client secret.

Scopes

ScopeAllows
metadata:readList templates, submissions, jobs, exports, usage and events. No candidate names or CV text.
candidate:readRead selected candidate facts with evidence, only when the workspace sharing policy is on
drafts:writeUpload CVs, create upload links, suggest changes for human review, import a selected Lever attachment
previews:writeQueue draft PDF previews
exports:writeExport a submission that already has a valid human approval
artifacts:readCreate short-lived download handles and download approved files

Request the smallest set you need. A request without the right scope returns 403 with insufficient_scope and the required scope in the WWW-Authenticate header.

Endpoints

All paths are relative to https://cvpitch.app/integrations/v1.

MethodPathScopePurpose
GET/meanyThe workspace, credential type and granted scopes; useful as a connection test
GET/event-typesanyEvery event type with a description
GET/templatesmetadata:readList client templates with IDs and versions
GET/usagemetadata:readRead workspace usage for the period
GET/submissionsmetadata:readList submissions (metadata only), with limit and offset
GET/submissions/{id}metadata:readStage, current revision, fingerprint and a review link
POST/documentsdrafts:writeUpload a CV as multipart form data
GET/jobs/{id}metadata:readProcessing job status
POST/submissions/{id}/evidencecandidate:readRead selected facts by field path, with masked evidence
POST/submissions/{id}/proposalsdrafts:writeStage suggested changes for human review
POST/submissions/{id}/previewspreviews:writeQueue a draft PDF preview
POST/submissions/{id}/exportsexports:writeExport an approved submission
GET/exports/{id}metadata:readExport status and file IDs
POST/artifact-handlesartifacts:readCreate a five-minute download handle for an approved file
GET/artifacts/{handle}artifacts:readDownload the approved DOCX or PDF
GET/eventsmetadata:readPoll events with a cursor, optionally filtered by type
GET, POST/hooksmetadata:read (owner credential)List or create REST hook subscriptions for one event type
DELETE/hooks/{id}metadata:read (owner credential)Remove a REST hook subscription
POST/connectors/importdrafts:writeImport a selected Lever attachment
POST/connectors/attach-backexports:write and artifacts:readAttach an approved file to a Lever opportunity

Typical flow

  1. POST /documents with the CV file and an Idempotency-Key header. The response contains a submission_id and a job_id.
  2. Poll GET /jobs/{id}, or listen for webhooks, until extraction finishes.
  3. A recruiter reviews and approves the submission in CVPitch, using the review_url from GET /submissions/{id}.
  4. POST /submissions/{id}/exports with the expected_revision and fingerprint from the submission's metadata and an idempotency_key. If the submission changed or is not approved, you get 409 (for example approval_stale).
  5. GET /exports/{id} until the export is ready, then create a handle with POST /artifact-handles and download the file within five minutes.

Idempotency

Operations that create work take an idempotency key of 1 to 100 characters: the Idempotency-Key header on uploads and the idempotency_key field on exports and Lever operations. Repeating a request with the same key and the same data returns the original result instead of doing the work twice. Reusing a key with different data returns 409 with idempotency_conflict. Generate a new key for each logical operation and reuse it only for retries.

Pagination and events

GET /submissions and GET /events accept limit from 1 to 100, and GET /submissions also takes an offset up to 10,000. GET /events takes an after cursor and returns items plus next_cursor; store the cursor and pass it on the next call. Events contain IDs, statuses and timestamps only.

Errors and limits

Errors use a consistent JSON shape: an error object with a code, a human-readable message and a request_id. Common statuses are 401 (missing, expired or revoked token), 403 (insufficient scope or a sharing policy not enabled), 404, 409 (stale revision, missing approval, idempotency conflict) and 429 (rate limited).

  • Each credential can make up to 120 requests per minute.
  • Uploads accept the same files as the app: PDF, DOCX, DOC, RTF, ODT and TXT (1 MiB at most), and PNG, JPEG, WebP or TIFF images. Files can be up to 10 MiB, PDFs up to 20 pages, multi-page TIFF scans up to 10 pages, and extracted text up to 120,000 characters. Your plan's upload allowance and per-workspace upload rate limits apply.
  • File types are recognised by content: an unsupported type returns 415 (unsupported_type) and a file that does not match its extension returns 422 (invalid_signature).
  • Scanned PDFs and images are read with OCR at 1 AI credit per page; text PDFs and Word files never use credits. An image upload is refused with 402 (credits_exhausted) when the workspace has no credits left. A scanned PDF is detected during processing, so if credits run short its job fails with the same code.
  • Download handles expire after five minutes and only work with the credential that created them.
  • MCP tool arguments are limited to 64 KiB and results to 512 KiB.

Webhooks

Webhooks deliver an HTTPS POST with a JSON body to your endpoint. Workspace owners add webhook endpoints in the app, or create REST hook subscriptions through the API. Destinations must be HTTPS addresses that resolve to public IP addresses; redirects are not followed. Event types are:

EventWhen it fires
submission.ready_for_reviewA CV finished processing and is ready for human review
submission.approvedA recruiter approved the current revision
export.completedAn approved DOCX and PDF pair is ready to download
ats.pushedApproved files were attached to a candidate record in a connected ATS or CRM
share.createdA tracked client share link was created
share.viewedA client opened a shared submission
share.feedbackA client left feedback on a shared submission
talent.enquiryA visitor sent an enquiry from the agency talent page
job.queued, job.running, job.succeeded, job.cancelledA processing or rendering job changed state
job.failedProcessing or rendering failed (error code only)

GET /event-types returns the current list. Payloads carry IDs, statuses, counts and relative links only, never candidate text.

REST hooks

Automation platforms that use REST hooks can subscribe without the app: POST /hooks with {"event": "submission.approved", "target_url": "https://..."} using an API key or OAuth token that belongs to a workspace owner. The response includes the hook ID and a signing secret, shown once. Deliveries are signed exactly like other webhooks. Remove the subscription with DELETE /hooks/{id}.

Verifying signatures

Each delivery includes three headers: X-CVPitch-Event (the event ID), X-CVPitch-Timestamp (Unix seconds) and X-CVPitch-Signature (the text v1= followed by a hex-encoded digest). To verify:

  1. Read the raw request body as bytes, before any JSON parsing.
  2. Build the signed string: the timestamp, a full stop, the event ID, a full stop, then the raw body.
  3. Compute HMAC-SHA256 of that string with your webhook signing secret and hex-encode it.
  4. Compare v1= plus your result with the X-CVPitch-Signature header using a constant-time comparison.
  5. Reject deliveries whose timestamp is outside your replay window, for example five minutes.
  6. Deduplicate on the event ID, because a delivery can be retried.

Respond with any 2xx status quickly and do slow work afterwards. Each event gets up to five delivery attempts, with increasing delays between them.

MCP server

The remote MCP server at https://cvpitch.app/mcp uses the Streamable HTTP transport with JSON responses over POST; the protocol version it supports is returned when your client initialises (currently 2025-11-25). Clients authenticate with an OAuth access token issued for the MCP resource. Tools currently include the following, listed according to the scopes granted:

ToolScope
search, fetch, get_workspace_summarymetadata:read
list_templates, get_usage, list_submissions, get_submission_status, get_job_status, get_export_statusmetadata:read
get_candidate_evidencecandidate:read
create_draft_previewpreviews:write
export_approved_submissionexports:write
create_artifact_handleartifacts:read
create_upload_link, suggest_candidate_changes, import_selected_attachmentdrafts:write

search and fetch return submission metadata and review links, never candidate content. create_upload_link returns a short-lived link that opens the upload screen in the recruiter's signed-in browser, so no file passes through the assistant. export_approved_submission consumes an existing human approval and never grants one. suggest_candidate_changes stages a proposal for a recruiter to accept. Read the Model Context Protocol entry and our MCP guide for background.

Data handling for integrators

  • Metadata endpoints never return candidate names or CV text.
  • get_candidate_evidence and the evidence endpoint return only the field paths you request, with quotes masked according to the workspace sharing policy. Recruiter notes and raw source blocks are withheld.
  • Anything returned to an AI assistant is processed by that assistant's provider.
  • Revoking a key, removing a member or deleting a submission ends access immediately.

Connectors and email intake

Native ATS and CRM connectors (Greenhouse, Lever, Workable, Ashby, Teamtailor, Recruitee, SmartRecruiters, Recruit CRM, Crelate and Manatal) and format-by-email are set up by a workspace owner in the app rather than through this API, and recruiters import and attach files from the app. Their results reach your systems through the same events: an imported or emailed CV produces submission.ready_for_review, and attaching approved files to an ATS produces ats.pushed. The older /connectors/import and /connectors/attach-back endpoints and the import_selected_attachment MCP tool use a separate Lever key saved under Integrations. See integrations for setup.

See security for the wider picture. API access is included on every plan; see pricing.

Frequently asked questions

Can the API approve a submission?

No. Approval is a human action in the CVPitch app, tied to the exact revision, template version and contact-removal policy. The API and MCP tools can only export submissions that are already approved.

Which events can I subscribe to?

Submission ready for review, submission approved, export completed, files attached to an ATS, share link created, viewed and answered, talent page enquiry, and job queued, running, succeeded, cancelled or failed. Payloads carry IDs, statuses and links only. Poll GET /events if you cannot receive webhooks.

Do you have SDKs or a Zapier app?

There are no official SDKs, and dedicated Zapier, Make and n8n apps are not published yet. The API is plain HTTPS and JSON with a public OpenAPI 3.1 document and REST hooks, so the platforms' generic webhook and HTTP steps work with it; see integrations.

How do I test without real candidate data?

Use synthetic CVs that you write yourself, never real candidates' documents, while you build. Start with a free trial workspace and create an API key with only metadata:read while you explore.

Turn your next CV into a client-ready submission

Upload a candidate CV, check every fact against the source, remove contact details and export your agency’s branded DOCX and PDF. Your first 10 CVs are free.

Start free See how it works

Send your next candidate CV in your agency’s format

CVPitch reformats candidate CVs into your branded template, checks every fact against the source and removes contact details on your terms. Start with 10 free CVs.

Start free See pricing