GTM Atelier  //  Resora  //  Console
v1.0.0·build 2026-05-19Live
Section 01 · Adding data

Adding
data.

Paste-ready request bodies for Clay’s “Send to Webhook” action. Every scenario uses the same envelope — { provider, payload, external_id? } — and the same headers. Pick a scenario from the rail, copy the body, paste into Clay’s HTTP Request Body field, adjust the column mappings.

01

Endpoint

POSThttps://hcpocrfabfthlvgilymd.supabase.co/functions/v1/companies

Per-row webhook fired from Clay's Companies table. The upsert is idempotent on payload.domain — use the same endpoint for find-companies output and re-enrichment runs.

02

Headers

Authorization: Bearer <SUPABASE_SERVICE_ROLE_KEY>
Content-Type: application/json
Use the sb_secret_* from Supabase Dashboard → Settings → API. The legacy service_role JWT still works but is on the deprecation path.
03

Request body

{
  "provider": "clay",
  "payload": {
    "domain": "{{column: domain}}",
    "name": "{{column: name}}",
    "website": "{{column: website}}",
    "linkedin_url": "{{column: linkedin_url}}",
    "industry": "{{column: industry}}",
    "employee_count": "{{column: employee_count}}",
    "country": "{{column: country}}",
    "description": "{{column: description}}"
  },
  "external_id": "{{column: clay_row_id}}"
}
The {{column: name}} syntax is Clay’s mapping shorthand — replace with your actual column names. The full canonical field list lives in the API reference below.
Note 01
Why the envelope?

The API doesn’t couple itself to one provider’s schema.

Every adapter (clay, firmable, icypeas, prospeo, manual) receives the raw payload and is responsible for normalising it into the canonical row shape before the upsert.

This keeps Clay’s output untouched (no fragile field renaming in Clay’s webhook builder), lets the adapter handle shape changes server-side (one deploy fixes all clients), and gives every raw payload a permanent audit row in raw_records.

Section 03

API Reference.

↓ Reference below
Section 04 · API Reference

Endpoints.

9 endpoints · 4 schemas · service-role auth required

GET/companies/{domain}

Enrich Company

Parameters
NameInRequiredTypeDescription
domainpathrequiredstring
includequeryoptionalenum
Responses
200

OK

application/jsonClayCompany
404

Not found

Code samples
curl -s 'https://hcpocrfabfthlvgilymd.supabase.co/functions/v1/companies/acme.com?include=stats' \
  -H 'Authorization: Bearer <SERVICE_ROLE_KEY>'
GET/companies/{domain}/contacts

Find Contacts using Company Domain

Parameters
NameInRequiredTypeDescription
domainpathrequiredstring
titlequeryoptionalstringe.g. 'ilike.*CFO*'
limitqueryoptionalinteger
offsetqueryoptionalinteger
Responses
200

OK

application/json
Code samples
curl -s 'https://hcpocrfabfthlvgilymd.supabase.co/functions/v1/companies/acme.com/contacts?title=ilike.*CFO*&limit=50' \
  -H 'Authorization: Bearer <SERVICE_ROLE_KEY>'
POST/companies

Add Company (Clay webhook target)

Ingest a single company row. The standard body is `{ provider, payload, external_id? }`: `provider` selects which adapter normalizes `payload` before the canonical upsert. For the Resora Firmable-list-to-Clay-enrichment flow, Clay sends one HTTP request per row with `{ provider: "firmable", firmable_company_id, enriched_company }`. The retained `firmable_company_id` becomes the canonical `firmable_id` lookup, and the first object in `enriched_company` supplies the enriched company fields. `enriched_company` may be Clay's object value or a one-item array. Idempotent on `firmable_id` when present, otherwise `domain` or LinkedIn URL. Re-POSTing the same lookup key updates the existing row, bumps `enriched_at` (clay only), and appends to `sources[]` without duplicating.

Request body
application/jsonrequired
{
  "provider": "firmable",
  "firmable_company_id": "f000000517970",
  "enriched_company": [
    {
      "url": "https://www.linkedin.com/company/igniteco",
      "name": "Ignite",
      "slug": "igniteco",
      "domain": "igniteco.com",
      "website": "https://igniteco.com/",
      "industry": "Staffing and Recruiting",
      "country": "AU",
      "employee_count": 233
    }
  ]
}
Responses
200

Canonical company row

application/jsonClayCompany
422

Adapter rejected or skipped the payload

Code samples
curl -s -X POST 'https://hcpocrfabfthlvgilymd.supabase.co/functions/v1/companies' \
  -H 'Authorization: Bearer <SERVICE_ROLE_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{
    "provider": "firmable",
    "firmable_company_id": "f000000517970",
    "enriched_company": [{
      "url": "https://www.linkedin.com/company/igniteco",
      "name": "Ignite",
      "slug": "igniteco",
      "domain": "igniteco.com",
      "website": "https://igniteco.com/",
      "industry": "Staffing and Recruiting",
      "country": "AU"
    }]
  }'
GET/contacts/{linkedin_slug}

Enrich Contact

Parameters
NameInRequiredTypeDescription
linkedin_slugpathrequiredstring
includequeryoptionalenum
Responses
200

OK

application/jsonClayContact
404

Not found

Code samples
curl -s 'https://hcpocrfabfthlvgilymd.supabase.co/functions/v1/contacts/jdoe?include=company' \
  -H 'Authorization: Bearer <SERVICE_ROLE_KEY>'
POST/contacts

Add Contact (Clay webhook target)

Ingest a single contact row. The standard body is `{ provider, payload, external_id? }`: `provider` selects which adapter normalizes `payload` before the canonical upsert. For the Resora Firmable-list-to-Clay-person-enrichment flow, Clay sends one HTTP request per row with `{ provider: "firmable", id, firmable_company_id, linkedin_company_url, domain, job_title, linkedin_profile, enrich_person }`. The retained contact `id` becomes `contacts.firmable_id`, `firmable_company_id` resolves the internal `primary_company_id`, and `enrich_person` supplies the enriched person fields. Idempotent on `firmable_id` when present, otherwise LinkedIn URL or slug. If a new Firmable id conflicts with a LinkedIn lookup already owned by another Firmable id, the write fails instead of rewriting the existing row.

Request body
application/jsonrequired
{
  "provider": "firmable",
  "id": "fp000123456789",
  "firmable_company_id": "f000000517970",
  "linkedin_company_url": "https://www.linkedin.com/company/labour-solutions-australia",
  "domain": "laboursolutions.com.au",
  "job_title": "WA Regional Director",
  "linkedin_profile": "https://www.linkedin.com/in/karl-stockman-85134761",
  "enrich_person": {
    "org": "Labour Solutions Australia",
    "url": "https://www.linkedin.com/in/karl-stockman-85134761",
    "name": "Karl Stockman",
    "slug": "karl-stockman-85134761",
    "title": "WA Regional Director",
    "country": "Australia",
    "headline": "Manager at Labour Solutions Australia",
    "first_name": "Karl",
    "last_name": "Stockman",
    "profile_id": 218819581,
    "connections": 94,
    "num_followers": 96,
    "jobs_count": 1,
    "location_name": "Greater Perth Area, Australia",
    "latest_experience": {
      "url": "https://www.linkedin.com/company/labour-solutions-australia",
      "title": "WA Regional Director",
      "company": "Labour Solutions Australia",
      "company_domain": "laboursolutions.com.au",
      "is_current": true
    }
  }
}
Responses
200

Canonical contact row

application/jsonClayContact
422

Adapter rejected or skipped the payload

Code samples
curl -s -X POST 'https://hcpocrfabfthlvgilymd.supabase.co/functions/v1/contacts' \
  -H 'Authorization: Bearer <SERVICE_ROLE_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{
    "provider": "firmable",
    "id": "fp000123456789",
    "firmable_company_id": "f000000517970",
    "linkedin_company_url": "https://www.linkedin.com/company/labour-solutions-australia",
    "domain": "laboursolutions.com.au",
    "job_title": "WA Regional Director",
    "linkedin_profile": "https://www.linkedin.com/in/karl-stockman-85134761",
    "enrich_person": {
      "org": "Labour Solutions Australia",
      "url": "https://www.linkedin.com/in/karl-stockman-85134761",
      "name": "Karl Stockman",
      "title": "WA Regional Director"
    }
  }'
POST/ingest

Raw push (batch / async)

Request body
application/jsonIngestBodyrequired
Responses
200

Queued or processed

422

Sync-mode adapter failure

Code samples
curl -s -X POST 'https://hcpocrfabfthlvgilymd.supabase.co/functions/v1/ingest' \
  -H 'Authorization: Bearer <SERVICE_ROLE_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{
    "provider": "clay",
    "kind": "company",
    "payload": {"name": "Acme", "website": "https://acme.com"},
    "external_id": "clay-acme-001",
    "sync": false
  }'
POST/firmable-find-contacts/enqueue

Queue Firmable contact searches

Marks untouched Firmable-backed companies as pending for contact search when they have zero linked canonical contacts. This does not call Firmable. It only prepares work for the throttled worker.

Request body
application/json
Responses
200

Queue count

application/json
Code samples
curl -s -X POST 'https://hcpocrfabfthlvgilymd.supabase.co/functions/v1/firmable-find-contacts/enqueue' \
  -H 'Authorization: Bearer <SERVICE_ROLE_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{"limit":500}'
POST/firmable-find-contacts/process

Process Firmable contact-search queue

Claims pending companies one at a time, calls Firmable People Search with only `{ companyId, selectedCountry: "AU" }`, and spreads 15-20 requests randomly across roughly one minute. A rolling 60-second guard prevents more than 20 Firmable search starts even if the worker overlaps with a manual invocation. Results are stored in `firmable_contact_search_runs` and `firmable_contact_candidates`. Candidate rows are for Clay enrichment; canonical `contacts` rows are created only when Clay posts enriched people back to `POST /contacts`.

Request body
application/json
Responses
200

Worker summary

application/json
Code samples
curl -s -X POST 'https://hcpocrfabfthlvgilymd.supabase.co/functions/v1/firmable-find-contacts/process' \
  -H 'Authorization: Bearer <SERVICE_ROLE_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{"min_requests":15,"max_requests":20}'
GET/admin/failed-raws

List failed raw_records (dead-letter)

Parameters
NameInRequiredTypeDescription
limitqueryoptionalinteger
offsetqueryoptionalinteger
Responses
200

OK

Code samples
curl -s 'https://hcpocrfabfthlvgilymd.supabase.co/functions/v1/admin/failed-raws?limit=100&offset=0' \
  -H 'Authorization: Bearer <SERVICE_ROLE_KEY>'

Schemas.

ClayCompany

NameTypeRequiredDescriptionExample
idstring<uuid>requiredCanonical internal company id.
domainstringoptionalLookup key, not the primary identity. Nullable.workforce.com.au
firmable_idstringoptionalNullable.f000001337357
namestringoptional
linkedin_urlstringoptionalNullable.
industrystringoptionalNullable.
employee_countintegeroptionalNullable.
countrystringoptionalNullable.
extrasobjectoptionalOpen shape — provider-specific extras stored as JSONB.

ClayContact

NameTypeRequiredDescriptionExample
idstring<uuid>requiredCanonical internal contact id.
firmable_idstringoptionalNullable.fp000003808937
linkedin_urlstringoptionalLookup key, not the primary identity. Nullable.https://www.linkedin.com/in/jdoe
linkedin_slugstringoptionalNullable.
namestringrequired
titlestringoptionalNullable.
primary_company_idstring<uuid>optionalNullable.
primary_company_domainstringoptionalNullable.
primary_company_firmable_idstringoptionalNullable.
emailsarray<object>optionalItems: { value, type, source }.
phonesarray<object>optionalItems: { value, type, source }.

IngestBody

NameTypeRequiredDescriptionExample
providerenum<string>requiredValues: clay, manual, firmable, icypeas, prospeo.manual
kindenum<string>requiredValues: company, contact.
payloadobjectrequired
external_idstringoptionalNullable.
fetched_atstring<date-time>optionalNullable.
syncbooleanoptionalDefault: false.

FirmableContactCandidate

NameTypeRequiredDescriptionExample
idstring<uuid>optional
run_idstring<uuid>optional
company_idstring<uuid>optional
firmable_company_idstringoptionalf000000619177
firmable_person_idstringoptionalfp000013703241
namestringoptionalNullable.Jane Hughes
titlestringoptionalNullable.National Account Director - Finance
linkedin_slugstringoptionalNullable.janehughesfinance
linkedin_urlstringoptionalNullable.https://www.linkedin.com/in/janehughesfinance
has_emailbooleanoptionalNullable.
has_phonebooleanoptionalNullable.
has_mobilebooleanoptionalNullable.
clay_statusenum<string>optionalValues: pending, sent, enriched, skipped, failed.