OSPRY Docs

API reference (v1)

OSPRY contact contract

Version 2026-09-04 · Download the OpenAPI document

Interactive explorer

Open the API explorer: browse every operation, build a request, and copy it as curl, JavaScript or Python. Or load the OpenAPI document into your own client.

Servers

  • https://{customerPublicId}.lgnapi.com

    Canonical edge host. Serves the bearer push (POST /v1/contacts), the generic inbound webhook (POST /v1/contacts/{sourceId}) and the HighLevel webhook (POST /v1/contacts/highlevel). Not used for GET /api/v1/schema or POST /api/contacts/links, which the origin serves directly.

  • https://app.ospry.ai

    The portal origin. Canonical for GET /api/v1/schema and POST /api/contacts/links. Deprecated dual-serve fallback for the push and webhook paths (prd-045-03), reachable there under different routes: POST /api/contacts mirrors POST /v1/contacts, and POST /api/contacts/webhook/{sourceId} mirrors POST /v1/contacts/{sourceId}. The HighLevel webhook is served by the edge host only. The origin push fallback accepts a portal session in place of an API key. It may answer 429 with Retry-After. Either origin fallback may answer 200 with a synchronous result instead of 202 when the durable queue is unavailable. The origin webhook fallback applies no rate limit.

Authentication

SchemeHow to send itNotes
ApiKeyAuthBearerHTTP bearerA tenant API key (`lsk_`-prefixed) presented as `Authorization: Bearer <key>`. A present-but-wrong or present-but-blank key answers 401 and never falls back to any other credential. Equivalent to ApiKeyAuthHeader; present exactly one of the two forms. The key is a secret: send it only from server-side code, never from a browser or a mobile app bundle.
ApiKeyAuthHeaderheader parameter x-api-keyA tenant API key presented as the `x-api-key` header. Equivalent to ApiKeyAuthBearer; present exactly one of the two forms.
SourceTokenHeaderheader parameter x-webhook-tokenThe per-source inbound webhook token. This is the preferred form: use it whenever the sending platform can set a custom header. Equivalent to SourceTokenQuery; when both are present, this header is the one checked.
SourceTokenQueryquery parameter tokenThe per-source inbound webhook token as a query parameter. A fallback ONLY for platforms that cannot set a custom header: a URL that carries a token is routinely written to access, proxy and CDN logs, to browser history, and to the sending platform's own run history. Prefer SourceTokenHeader, never paste a token-bearing URL into a shared document or ticket, and rotate the token from the portal's Inbound Connections screen if such a URL is exposed. Equivalent to SourceTokenHeader, which takes precedence when both are present.

Operation groups

  • Contacts

    The tenant-facing contact push, inbound webhook and link-minting operations.

  • Schema

    The machine-readable field contract.

  • Webhooks

    Operations in the Webhooks group of the OSPRY Contacts API v1.

Overview

Version 2026-09-04. OpenAPI 3.1.0.

Servers

  • https://{customerPublicId}.lgnapi.com: Canonical edge host. Serves the bearer push (POST /v1/contacts), the generic inbound webhook (POST /v1/contacts/{sourceId}) and the HighLevel webhook (POST /v1/contacts/highlevel). Not used for GET /api/v1/schema or POST /api/contacts/links, which the origin serves directly.
  • https://app.ospry.ai: The portal origin. Canonical for GET /api/v1/schema and POST /api/contacts/links. Deprecated dual-serve fallback for the push and webhook paths (prd-045-03), reachable there under different routes: POST /api/contacts mirrors POST /v1/contacts, and POST /api/contacts/webhook/{sourceId} mirrors POST /v1/contacts/{sourceId}. The HighLevel webhook is served by the edge host only. The origin push fallback accepts a portal session in place of an API key. It may answer 429 with Retry-After. Either origin fallback may answer 200 with a synchronous result instead of 202 when the durable queue is unavailable. The origin webhook fallback applies no rate limit.

Security schemes

  • ApiKeyAuthBearer (http, bearer): A tenant API key (lsk_-prefixed) presented as Authorization: Bearer <key>. A present-but-wrong or present-but-blank key answers 401 and never falls back to any other credential. Equivalent to ApiKeyAuthHeader; present exactly one of the two forms. The key is a secret: send it only from server-side code, never from a browser or a mobile app bundle.
  • ApiKeyAuthHeader (apiKey, in header, x-api-key): A tenant API key presented as the x-api-key header. Equivalent to ApiKeyAuthBearer; present exactly one of the two forms.
  • SourceTokenHeader (apiKey, in header, x-webhook-token): The per-source inbound webhook token. This is the preferred form: use it whenever the sending platform can set a custom header. Equivalent to SourceTokenQuery; when both are present, this header is the one checked.
  • SourceTokenQuery (apiKey, in query, token): The per-source inbound webhook token as a query parameter. A fallback ONLY for platforms that cannot set a custom header: a URL that carries a token is routinely written to access, proxy and CDN logs, to browser history, and to the sending platform's own run history. Prefer SourceTokenHeader, never paste a token-bearing URL into a shared document or ticket, and rotate the token from the portal's Inbound Connections screen if such a URL is exposed. Equivalent to SourceTokenHeader, which takes precedence when both are present.

Contact

Schema Contact (object)

The shared contact object. It is the webhook body's subject verbatim and the read contract's single-resource body. Every key of a caller's key set K appears exactly once, either here as a value or in missing as a reason, never both and never neither.

Properties

  • company (object, required): The firmographic fields.
    • domain (string | null): The registrable domain of the person's employer.
    • employee_count (string | null): The employee-count band of the person's employer, as delivered by the provider.
    • est_revenue (string | null): The revenue band of the person's employer, as delivered by the provider.
    • industry (string | null): The industry of the person's employer, as the resolving provider bands it.
    • linkedin_url (string | null): The organization's LinkedIn page. Emitted in the export for a company record.
    • name (string | null): The denormalized name of the person's employer.
    • website (string | null): The company's website URL as delivered, kept alongside the normalized domain.
  • contract_version (const "2026-09-04", required): The dated contract version.
  • custom_fields (array of object, required): The tenant's own custom fields. Tier 1, always present (parent OD-27).
  • handles (object, required): Email and phone handles. emails[] and phones[] are tier 2.
    • business_email (string | null): The person's work email address, stored case-insensitively.
    • emails (array of object): Tier 2. Empty when the tier is not enabled.
    • phones (array of object): Tier 2. Empty when the tier is not enabled.
  • id (string, required): The tenant-scoped identifier of the resolved person record.
  • identity (object, required): The subject identity fields.
    • first_name (string | null): The person's given name.
    • full_name (string | null): The person's full name, joined from the first and last name at ingest.
    • last_name (string | null): The person's family name.
    • linkedin_url (string | null): The person's LinkedIn profile URL. Half of the row's unique key, so the provider upsert never overwrites it.
    • seniority (string | null): The seniority band both providers return. Elected by the resolver today and landed by the winner writer this pull request ships.
    • title (string | null): The person's job title at the resolved company.
  • links (object, required): Absolute links to this subject.
    • portal (string | null): The portal page for this subject.
    • self (string | null): The read-contract URL for this subject.
  • location (object, required): The subject location fields.
    • city (string | null): The coarse business location the resolving provider reports. It is not the home address, which is a tier-3 trait.
    • postal_code (string | null): The coarse postal code the resolving provider reports for the business location.
    • state (string | null): The coarse business region the resolving provider reports.
  • missing (object, required): Every key in this caller's key set K that carries no value, mapped to one of the five closed reasons.
  • object (const "contact", required): Always the literal "contact".
  • provenance (object, required): How this subject was resolved and when it was seen.
    • first_seen_at (string): When this person was first resolved for the tenant.
    • last_seen_at (string): When this person was last re-resolved. Refreshed on every provider upsert.
    • name_source (enum "enrichment", "form", "manual", "provider", null): Which class of writer last set the name columns. The ADR-031 ladder ranks form above manual above enrichment above provider, and NULL ranks as provider.
    • resolved_by (string): Which vendor resolved this person. A per-ROW insert-only stamp, never per-field provenance, and masked to a tier label on every customer surface.
  • subject_type (enum "company_profile", "contact", "person_profile", required): Which catalogued subject this object describes.
  • traits (array of object, required): Tier 3 (sensitive_traits): the household, demographic and financial traits. The tier is available to every account and is off by default on each connector, so this array carries values only once the customer enables it on that connector. Until then it is empty and every tier-3 key is named in missing with the reason withheld_tier.

ContactList

Schema ContactList (object)

The read contract list body. Declared now and produced by the follow-on (parent NG15), so push and pull cannot diverge before pull is built.

Properties

  • contract_version (const "2026-09-04", required)
  • data (array of Contact, required)
  • has_more (boolean, required)
  • next_cursor (string | null): An opaque keyset cursor.
  • object (const "list", required)

FieldPolicy

Schema FieldPolicy (object)

The per-delivery accounting of what the caller received and what it did not. permitted_tiers is what the tenant may enable; enabled_tiers is what this integration has on.

Properties

  • enabled_tiers (array of enum 1, 2, 3, required)
  • included (integer, required)
  • missing (integer, required)
  • missing_reason (object, required): A count per reason. Every key is one of the five closed reasons.
  • permitted_tiers (array of enum 1, 2, 3, required)
  • withheld_tiers (array of enum "contact_handles", "sensitive_traits", required)

WebhookEventV2

Schema WebhookEventV2 (object)

The whole opt-in v2 outbound body. Its subject is a Contact; a whole body deliberately does NOT validate against Contact, because the envelope carries nine keys the subject does not.

Properties

  • classification (string): Omitted when empty. The velocity-rule label.
  • contract_version (const "2026-09-04", required)
  • emitted_at (string, required)
  • event (const "visitor.identified", required)
  • field_policy (FieldPolicy): The per-delivery accounting of what the caller received and what it did not. permitted_tiers is what the tenant may enable; enabled_tiers is what this integration has on.
    • enabled_tiers (array of enum 1, 2, 3, required)
    • included (integer, required)
    • missing (integer, required)
    • missing_reason (object, required): A count per reason. Every key is one of the five closed reasons.
    • permitted_tiers (array of enum 1, 2, 3, required)
    • withheld_tiers (array of enum "contact_handles", "sensitive_traits", required)
  • id (string, required): The visit_event id, and the X-Sight-Idempotency-Key value.
  • is_repeat (boolean, required)
  • served_from (string): Omitted when empty. "cache" on a serve-local of a recognized return.
  • subject (Contact, required): The shared contact object. It is the webhook body's subject verbatim and the read contract's single-resource body. Every key of a caller's key set K appears exactly once, either here as a value or in missing as a reason, never both and never neither.
    • company (object, required): The firmographic fields.
    • contract_version (const "2026-09-04", required): The dated contract version.
    • custom_fields (array of object, required): The tenant's own custom fields. Tier 1, always present (parent OD-27).
    • handles (object, required): Email and phone handles. emails[] and phones[] are tier 2.
    • id (string, required): The tenant-scoped identifier of the resolved person record.
    • identity (object, required): The subject identity fields.
    • links (object, required): Absolute links to this subject.
    • location (object, required): The subject location fields.
    • missing (object, required): Every key in this caller's key set K that carries no value, mapped to one of the five closed reasons.
    • object (const "contact", required): Always the literal "contact".
    • provenance (object, required): How this subject was resolved and when it was seen.
    • subject_type (enum "company_profile", "contact", "person_profile", required): Which catalogued subject this object describes.
    • traits (array of object, required): Tier 3 (sensitive_traits): the household, demographic and financial traits. The tier is available to every account and is off by default on each connector, so this array carries values only once the customer enables it on that connector. Until then it is empty and every tier-3 key is named in missing with the reason withheld_tier.
  • tier (enum "company", "person", required)
  • visit (object): The visit that produced this event.
    • captured_url (string | null)
    • domain_id (string | null)
    • referrer (string | null)
    • seen_at (string | null)
    • visitor_id (string | null)