Skip to content

Check prior outreach for a contact

When to use this guide: Read this when a workflow — an agent, a low-code HTTP module, or an enrichment column — should skip or delay a contact you already reached.

GET /api/v1/contacts/outreach is one authenticated GET. There are no tool-specific routes. Pass a contact email and/or social profileUrl; the response says whether that person was already emailed, called, or social-messaged, plus last-touch recency and hard Do-Not-Contact signals.

Any client that can send a Bearer GET works. ZoomInfo, Clay, Databar, and Freckle below are worked examples of the same call — jump to the one you use, or copy Shared request into an agent or HTTP module.

  • OutboundSync account with API access enabled on at least one CRM connection
  • An API key from the OutboundSync dashboard (osapi_…) — see Creating API keys
  • Sequencer webhooks flowing into OutboundSync (CRM sync optional — engagement lives in the OutboundSync event ledger)
FieldValue
MethodGET
URLhttps://app.outboundsync.com/api/v1/contacts/outreach
HeaderAuthorization: Bearer osapi_<your_key>

Query (at least one required):

  • email ← contact email
  • profileUrl ← social profile URL (/in/…, /pub/…, or X). Repeat or comma-separate, max 5. All identities on one request are OR-unioned — send identities for the same contact only.

Useful JSON paths for filters: found, query.email / query.profileUrls, summary.everContacted, summary.everEmailed / summary.everSocialTouched, summary.lastTouchAt / summary.daysSinceLastTouch / summary.lastEventType / summary.lastPlatform, outcomes.replied / outcomes.bounced / outcomes.unsubscribed, doNotContact.value / doNotContact.reasons. Ignore blocklists.* in this release (evaluated is always false). Full shape: API v1 — contacts/outreach.

Optional readiness gate before a large run: GET /api/v1/account/status and skip when ready is false.

  1. For each contact, pass email and social profileUrl when available
  2. Keep contacts where doNotContact.value is false
  3. Keep contacts where found is false, or summary.daysSinceLastTouch is null, or it is ≥ your cadence (e.g. 90)
  4. Hand the remaining contacts to AEs (call / high-touch sequence)
  • General API: 120 requests / 60 seconds per account
  • Contact outreach: 600 requests / 60 seconds per account (separate bucket)

Respect Retry-After on HTTP 429. See Errors and rate limits.

  • Identity match is case-insensitive on stored to_email. HubSpot/Salesforce backfill to_email with the profile URL for social-only events; Attio, Close, HighLevel, and Pipedrive do not — pass email when you have it.
  • doNotContact is bounce + unsubscribe only. blocklists.matched is always false until evaluation ships — do not filter on it.
  • firstTouchAt / lastTouchAt are processing time, not sequencer event time. Category-only matches set found: true with daysSinceLastTouch: null.
  • everContacted ignores open/click-only and passive views/likes.

Contract notes live on the endpoint reference.

GTM Studio Custom Data Connector.

FieldValue
NameOutboundSync — Prior Outreach
Base URLhttps://app.outboundsync.com
Auth methodAPI Key
Key nameAuthorization
PlacementHeader
Key valueBearer osapi_<your_key>

Add an Enrich action: GET /api/v1/contacts/outreach with email and/or profileUrl. Use Test API, then generate output with test so workflow fields match ContactOutreachResponse. Optionally add a Retrieve action on GET /api/v1/account/status as the readiness gate.

Clay HTTP API enrichment column (Growth or higher). This is Clay as an API consumer. For syncing Clay’s native sequencer into your CRM, see the Clay engagement integration instead.

  1. Table → Add enrichmentHTTP API
  2. Prefer the Configure tab (or Generate and point Sculptor at https://app.outboundsync.com/api/v1/openapi.json)

Map /Email and /LinkedIn URL (or your column names) onto email and profileUrl. Test one row, then run the table. Avoid unbounded parallel runs past 600 requests / 60 seconds.

Databar custom API enrichment.

  1. Workspace home → IntegrationsConnect a custom API
  2. Type Enrichment, method GET, URL as in Shared request

Save, then add it from Enrich → Add or use your own REST API. Map columns → Add ColumnsRun. On Databar Scale+, cap connector concurrency so you stay under 600 / 60s (for example ≤10 req/s sustained).

Freckle HTTP API column (Build plan or higher). Freckle does not publish developer docs for this column — labels may drift; verify in the UI before a large run.

Create a column → HTTP API → endpoint and Authorization header as in Shared request. Map JSON paths, test on one row, then run the rest.

Test the call against a contact you know you reached, then one you have not. Confirm found, doNotContact.value, and summary.daysSinceLastTouch. If the payload looks wrong, send the same query from Try the API so you can tell a mapping issue from an API issue.

Then apply the recipe: drop hard DNC, keep never-touched or aged-out contacts, and enroll the rest. Field-level contract notes stay on GET /api/v1/contacts/outreach. If you have been using a sequencer block list as a recency clock, the same filter belongs at enrollment — see Check prior outreach before you enroll.