> ## Documentation Index
> Fetch the complete documentation index at: /help/llms.txt
> Use this file to discover all available pages before exploring further.

# Attio

> Create or update Attio people records from LinkedIn campaigns, add hot contacts to a list, and let Attio changes steer the campaign.

> [!NOTE]
>
> **Pro plan.** Attio works through a connection, HTTP steps and listeners (**Wait for webhook**, **Call & wait**), which are part of Pro and Agency (and the free trial). Anything you already have keeps working on every plan. See [Plans and billing](/help/account/billing.md).

When someone accepts your invitation, a **Webhook / HTTP** step creates their person record in Attio, or updates it if one with the same email exists. Attio webhooks can then move the contact to another path in Kerux.

> [!NOTE]
>
> **How it connects:** Attio's REST API with an access token, and Attio webhooks. See Attio's [people records](https://docs.attio.com/rest-api/endpoint-reference/people/create-a-person-record) docs (including the assert behavior). Requests and answers follow Attio's docs.

## Before you start

* **An access token:** in Attio, open **Workspace settings > Developers**, create an integration and give it read and write access to records (and lists, if you add people to one). Copy its access token.

## 1. Connect Attio

In Kerux, open **Integrations > Connections**, click **Connect** on **Custom API** (under **Developers**):

* **How it signs in:** **Bearer token**, paste the token.
* **Base URL:** `https://api.attio.com`

Click **Save**, then **Test connection**.

## 2. Assert the person

Add a **Webhook / HTTP** step after **Invitation accepted**, pick the Attio connection, name it `attio` and paste:

```json theme={null}
{
  "method": "PUT",
  "url": "/v2/objects/people/records",
  "query": { "matching_attribute": "email_addresses" },
  "bodyType": "json",
  "body": {
    "data": {
      "values": {
        "email_addresses": ["{{email}}"],
        "name": [
          {
            "first_name": "{{contact.first_name}}",
            "last_name": "{{contact.last_name | optional}}",
            "full_name": "{{contact.full_name}}"
          }
        ],
        "linkedin": "{{contact.linkedin_url}}"
      }
    }
  }
}
```

With `PUT` and `matching_attribute`, Attio updates the person whose email matches and creates one when none does (its assert behavior). The answer has the record id at `data.id.record_id` and a link at `data.web_url`: `{{steps.attio.response.body.data.id.record_id}}`.

The assert call needs an email. For contacts without one, use `POST /v2/objects/people/records` (create) with the same body, which fails if the email already exists.

## 3. Let Attio steer the campaign

**1. Add a Wait for webhook step**

Choose **One shared URL + a match rule** and match the record id in Attio's payload to `{{steps.attio.response.body.data.id.record_id}}`. Click **Listen for test event**.

**2. Create the webhook in Attio**

In Attio's developer settings, add a webhook for record updates with the Kerux URL. Change a test record so Kerux gets a sample, then pick the fields to match and branch on.

## Test with one contact

In the campaign's **Builder**, click **Test** to open **Test on one contact**. The journey shows Attio's answer; open the record from `data.web_url`.

## Common errors

> [accordion] 403 or a scope error
>
> The integration lacks write access to records. Change its scopes in **Workspace settings > Developers**.

> [accordion] Conflict on email\_addresses
>
> You used the create endpoint for an email that already exists. Use the assert call above.

> [accordion] 400 about an attribute
>
> The attribute slug doesn't exist in your workspace (for example a custom LinkedIn attribute with another slug). Check the slugs in Attio's object settings.

Related: [Webhook steps](/help/integrations/webhook-steps.md), [Connections](/help/integrations/connections.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.