OpenSequence
DocsAPI referenceSDKs and CLIReference
Senders

Connect Attio

One Attio API key per project; the schema endpoint, how deals are selected, and what crm.* conditions can read.

Edit on GitHub

Attio is the CRM behind the read-only CRM port: conditions read the contact's person, company and open deal live at decision time. One workspace key per project.

curl
curl -X PUT $SEQ/v1/project/providers/attio -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"api_key":"…"}'
curl $SEQ/v1/project/providers/attio/schema -H "Authorization: Bearer $KEY"
# {"objects":[{"name":"person","attributes":[{"slug":"job_title","label":"Job title","type":"text"},…]},{"name":"company",…},{"name":"deal","attributes":[{"slug":"stage","label":"Stage","type":"status","values":["Lead","In Progress","Won 🎉","Lost"]},…]}]}

The key

PUT /v1/project/providers/attio probes the key (GET /v2/self) and refuses an invalid one. Encrypted, write-only; rotate by calling again.

The schema endpoint

GET /v1/project/providers/attio/schema lists the person, company and deal objects with their non-archived attributes (slug, label, type, and values for status and select attributes), fetched from Attio and cached for an hour. It is what a condition picker shows under crm.*.

What a condition can read

FieldValue
crm.person.exists, crm.company.exists, crm.deal.existswhether the lookup found one
crm.person.<slug>, crm.company.<slug>the attribute, flattened to a scalar (a status or select gives its title; a name gives the full name; an email its address; a list joins its items with commas)
crm.deal.stage, crm.deal.<slug>the same for the selected open deal
crm.deal.count_openhow many open deals are linked to the person or the company

The lookup: the person by the contact's email, the company by the email's domain (or the person's company when the domain matches nothing), then the deals associated with either. A deal is open unless its stage title starts with closed, won, lost or churn (case-insensitive, emoji ignored) or Attio flags the stage as a celebration. Among open deals the project chooses with settings.crm.deal_selection: newest_open (default), highest_value, or any_open (the oldest).

One lookup per contact per step, shared by every crm.* rule in the condition. When Attio is down, slow, or the person is not found, the fact is recorded as null with the error, so the rule does not match and the contact takes no; the journey shows why. See CRM conditions.

Writes

The CRM port is read-only in v1: nothing moves a deal, adds a note or changes an attribute. React to webhook events and write to Attio yourself; a crm_action node is planned once a second CRM adapter exists.

With mock providers

The mock CRM answers from settings.mock.crm on the project ({ "byEmail": { "dana@example.com": { "deal": { "stage": "Contacting" }, "openDeals": 1 } }, "byDomain": { … } }) so a crm.deal.stage condition can be exercised locally.

On this page