Description
@nodrel-dev/n8n-nodes-attio
An n8n community action node for the Attio CRM REST API (v2).
Connects with a single workspace API token and works with Records, Notes, and Tasks. Also usable as
an AI-Agent tool.
> Status: all three resources are implemented and verified live against a real workspace
> (see specs/001-attio-action-node/). This node has zero runtime dependencies and never reads
> environment variables or the filesystem.
Installation
In n8n: Settings → Community Nodes → Install, then enter @nodrel-dev/n8n-nodes-attio.
Requires Node.js >= 22.22 (self-hosted n8n).
Credentials
Create an Attio API credential and paste a workspace API token (stored as a password field, never
logged or echoed). The credential is validated with GET /v2/self when you save it — an invalid token
is rejected at the dialog.
Required token scopes (per operation group)
GET /v2/self passes for any valid token, so a missing scope only surfaces as a 403 at run time. The
node surfaces that 403 as a likely missing-scope error. Provision the token with the scopes below so it
works the first time.
| Operation group | Required scopes |
|—|—|
| Record Create / Upsert / Update / Delete | recordpermission:read-write + objectconfiguration:read |
| Record Get / Get Many / Search / List Attribute Values | recordpermission:read + objectconfiguration:read |
| Record List Entries | recordpermission:read + objectconfiguration:read + list_entry:read |
| Object dropdown (GET /v2/objects) | object_configuration:read |
| Note Create | note:read-write + objectconfiguration:read + recordpermission:read |
| Note Get / Get Many | note:read + objectconfiguration:read + recordpermission:read |
| Note Delete | note:read-write |
| Task Create / Update | task:read-write + objectconfiguration:read + recordpermission:read + user_management:read |
| Task Get / Get Many | task:read + objectconfiguration:read + recordpermission:read + user_management:read |
| Task Delete | task:read-write |
Operations
Pick a Resource (Record, Note, or Task), then an Operation. Every operation also exposes an
action label so the node can be used as an AI-Agent tool. The Object dropdown is populated
live from your workspace; you can also supply an object slug or ID via an expression.
Record (9)
| Operation | What it does | Attio endpoint |
|—|—|—|
| Create | Create a record from a JSON Values object | POST /v2/objects/{object}/records |
| Create or Update | Upsert, matching on an attribute slug (no duplicates) | PUT /v2/objects/{object}/records?matching_attribute=… |
| Get | Fetch one record by ID | GET /v2/objects/{object}/records/{record_id} |
| Update | Update a record; Multiselect Mode = Append (PATCH) or Overwrite (PUT) | PATCH / PUT …/records/{record_id} |
| Get Many | Filter (JSON or saved view), sort, paginate; Return All auto-pages | POST /v2/objects/{object}/records/query |
| Search | Cross-object free-text search | POST /v2/objects/records/search |
| Delete | Delete a record (returns { success, recordid }) | DELETE …/records/{recordid} |
| List Attribute Values | Historical values for one attribute | GET …/records/{record_id}/attributes/{attribute}/values |
| List Entries | List entries that reference the record | GET …/records/{record_id}/entries |
Values is a JSON object of attribute slugs → values, e.g. {"name": "Acme", "domains": ["acme.com"]}.
For Update, Append keeps existing multiselect values and adds the new ones; Overwrite replaces the
set so it equals exactly what you send.
Note (4)
| Operation | What it does | Attio endpoint |
|—|—|—|
| Create | Create a note linked to a parent record (Plaintext or Markdown) | POST /v2/notes |
| Get | Fetch one note by ID | GET /v2/notes/{note_id} |
| Get Many | List notes, optionally filtered by parent object/record; Return All | GET /v2/notes |
| Delete | Delete a note (returns { success, noteid }) | DELETE /v2/notes/{noteid} |
Task (5)
| Operation | What it does | Attio endpoint |
|—|—|—|
| Create | Create a task; link records and assign by email or member ID | POST /v2/tasks |
| Update | Update deadline / completion / links / assignees — content is write-once | PATCH /v2/tasks/{task_id} |
| Get | Fetch one task by ID | GET /v2/tasks/{task_id} |
| Get Many | List tasks, filtered by assignee / completion / linked record; Return All | GET /v2/tasks |
| Delete | Delete a task (returns { success, taskid }) | DELETE /v2/tasks/{taskid} |
Task content is set only at creation and cannot be changed later, so the Update surface has no
Content field. Assignee email is resolved to a workspace member server-side; a member ID is the
advanced alternative. To filter Get Many by a linked record, provide both the Linked Object and
Linked Record ID (Attio requires them together).
Example workflow
Create a company, then attach a note to it:
1. Attio → Record → Create
– Object: Companies
– Values: { "name": "Acme", "domains": ["acme.com"] }
2. Attio → Note → Create
– Parent Object: Companies
– Parent Record ID: ={{ $json.id.record_id }} (from step 1)
– Title: Imported from n8n
– Format: Plaintext
– Content: Created by an automated workflow.
The same pattern drives an AI Agent: add this node as a tool and the agent can call e.g.
Record → Create and Record → Get Many by their action names.
Rate limiting
Attio can return 429 with a Retry-After header in either form allowed by RFC 9110 §10.2.3 — an
HTTP date (a reset timestamp) or delta-seconds — depending on which limiter trips. Limits are
per endpoint: heavy query calls can be rate-limited on complexity, not just request rate. The node
reads both forms and surfaces a clear rate-limit message with the reset time or the delay. For
automatic resilience, enable n8n’s built-in Retry On Fail on the node.
Support boundary
Maintained by Nodrel as a community node. Issues and PRs welcome on GitHub. This is not an official
Attio product.
—
Maintainer notes — release & publishing
Releases are fully automated. Never bump the version by hand and never publish from a local machine.
- Conventional Commits drive everything. The squash-merge PR title is what
release-pleasereads, release-please(.github/workflows/release-please.yml) owns version bumps, the changelog, tags,publish.ymlisworkflow_call-only.release-please.ymlinvokes it directly once it has cut a- Recovery: to republish a tag whose publish never ran, dispatch
release-please.yml(not - Require the CI status check (
build-test) to pass before merge. - Require a conventional PR title (the
pr-titlejob) to pass. - Require PRs (no direct pushes) so every change flows through CI and a squash-merge title
ci.ymldeclares top-levelpermissions: contents: read.release-please.ymlneedscontents: write+pull-requests: write(only that workflow).publish.ymlneedscontents: read+id-token: write(only that workflow).
so it must be a valid conventional commit (enforced by the pr-title CI job).
and GitHub Releases. A feat:/fix: merge opens or updates a release PR; merging that PR cuts the
release.
release, and it publishes to npm with --provenance via OIDC Trusted Publishing — there is **no stored
NPM_TOKEN**, and the repo carries no Actions secrets at all.
It is deliberately not triggered by release: published. release-please creates the Release using
GITHUBTOKEN, and GitHub does not fire workflow-triggering events for GITHUBTOKEN actions, so that
trigger never fires. v0.2.4 was tagged and released but never reached npm before this was corrected.
publish.yml) with the tag input, e.g. v0.2.6. It skips automatically if that version is already
on npm, so re-running is safe.
npm Trusted Publisher (OIDC) setup
1. On npmjs.com, open the package’s Settings → Trusted Publishers.
2. Add a GitHub Actions publisher:
| Field | Value |
|——-|——-|
| Organization or user | nodrel-dev |
| Repository | n8n-attio-node |
| Workflow filename | release-please.yml |
| Environment | (leave empty) |
> ⚠️ The workflow is release-please.yml, not publish.yml — even though publish.yml is the
> file that actually runs npm publish. npm authorises the entry-point workflow of a run, not the
> reusable workflow it calls. Registering publish.yml fails as a misleading 404 on publish.
> Renaming release-please.yml breaks publishing until this config is updated to match.
3. No npm token is stored in GitHub. Both the calling job and publish.yml declare
permissions: id-token: write (OIDC needs it on parent and child); npm verifies the token and
attaches a provenance badge. Trusted publishing requires npm >= 11.5.1, so publish.yml upgrades
npm before publishing — Node 22.x ships npm 10.x, which has no trusted-publishing support.
Branch protection (main)
release-please can read.