Spec CV events

List spec CV sends

Changed on

Returns a keyset-paginated, agency-wide feed of speculative ("spec") CV sends (spec_cv_sent), oldest first — one row each time a candidate is pitched to a contact, whether by a direct Float send or by the first step of a campaign belonging to a speculative opportunity. A campaign counts once per contact, on whichever step type reached them first (email, call or LinkedIn), so a row means the pitch started rather than that an email specifically was sent. Each row records the candidate (person id and name), the contact it went to, the opportunity it belongs to (id and name), the user who sent it (name and email), the spec campaign id when applicable, and when. Nested references are resolved even when the underlying record was later deleted; a reference is null only when it could not be resolved.

Pagination (keyset): Responses carry pagination.hasMore and pagination.nextCursor rather than a page number or total count. Request the first page without a cursor, then send the returned nextCursor.cursorDate/cursorId on each subsequent request. This stays O(pageSize) at any depth, so it is safe for large historical backfills.

Backfill: Loop the cursor until hasMore is false; optionally bound with createdAfter to cap the horizon.

Incremental sync: Poll with createdAfter (the max sentAt from the previous run) and page the cursor within each poll. Overlap slightly and dedupe by id so a row written exactly at the boundary is never missed.

Dual-sync with /api/v1/prospects: Rows exist only from the feature go-live onward — spec CVs floated before that date have no event here. For a complete picture, backfill the legacy state from GET /api/v1/prospects first, then poll this feed with createdAfter for increments.

Access: Requires a key with BOTH Prospects and Users read scopes, since each row is enriched with the sending user (name and email).

Notes: Reverted sends (e.g. the speculative candidate was deleted) are excluded unless includeReverted=true. Repeat sends of the same candidate to the same contact on one opportunity are deduplicated at emit time, so they do not produce extra rows. This feed is eventually consistent (populated asynchronously).

get/api/v1/spec-cv-events

Request

Query parameters

string
OR
string date-time
string
OR
string date-time
includeReverted'true' | 'false'

Include sends that were later reverted (e.g. the speculative candidate was deleted). Defaults to false, so only effective sends are returned.

Example:false
pageSizeinteger

Items per page (max 100).

Example:25
cursorDatestring date-time

Keyset pagination cursor: the pagination.nextCursor.cursorDate returned by the previous request. Send together with cursorId to fetch the next page in stable order that stays O(pageSize) at any depth. Omit for the first page.

Example:2026-01-05T12:00:00.000Z
cursorIdstring uuid

Keyset pagination cursor: the pagination.nextCursor.cursorId returned by the previous request. Must be sent together with cursorDate.

Example:550e8400-e29b-41d4-a716-446655440000

Response

Paginated spec CV sends

status'ok' required

Example response

{
  "data": [
    {
      "candidate": {
        "firstName": "Michael",
        "lastName": "Scott"
      },
      "contact": {
        "firstName": "Michael",
        "lastName": "Scott"
      },
      "opportunity": {
        "name": "Connecting with Acme Corp"
      },
      "sentBy": {
        "name": "Jane Recruiter",
        "email": "jane@agency.com"
      }
    }
  ],
  "pagination": {
    "pageSize": 25
  }
}

Changes