ACTION_ID: attio_upsert_record NAME: Attio: Upsert Record CATEGORY: CRM CREDITS: 0 Create-or-update a record in any Attio object, matched on a unique attribute. ================================================================================ PREREQUISITE — USER ACTION REQUIRED ================================================================================ This action only works if the user has connected their Attio workspace in Floqer. The connection cannot be made via the API or by an AI agent. The user must do this themselves before this action will run: 1. Sign in to Floqer at https://app.floqer.com 2. Open the Connections page from the sidebar 3. Click Attio and complete the OAuth flow If the user has not connected Attio, this action will fail with a connection / authentication error. Before configuring or running this action, confirm with the user that the Attio connection exists. INDEX: 1. Inputs 2. Outputs 3. How to configure 4. Key notes 5. Where it fits in a workflow 6. When to use 7. When not to use ================================================================================ 1. INPUTS ================================================================================ attio_object (dynamicDropdown, required) Attio Object. Choose the Attio object to upsert into (People, Companies, Deals, or any custom object). Value is the object's api_slug. matching_attribute (dynamicDropdown, required) Matching Attribute. The attribute Attio matches on to decide whether to update an existing record or create a new one. ONLY UNIQUE attributes are listed — Attio rejects an upsert keyed on a non-unique attribute. add_attributes_and_their_values (jsonArray, required) Add Attributes and their Values. Select attributes from the object and add their values. Include the matching attribute — its value is what Attio looks the record up by. ================================================================================ 2. OUTPUTS ================================================================================ record_id (string) — Record ID. Record ID of the record that was created or updated. record_url (url) — Record URL. Direct link to the record in Attio. attributes (json) — Attributes. Every attribute on the record after the upsert, keyed by attribute slug — not just the ones sent. created_at (date) — Created At. When the record was first created in Attio. Older than this run means the upsert matched an existing record; equal to this run means it created one. ================================================================================ 3. HOW TO CONFIGURE ================================================================================ Resolve the dynamic field values via Get Action Field Options before configuring: POST /api/v1/workflows/{workflow_id}/sheets/{sheet_id}/actions/{action_instance_id}/options/attio_object (body: {}) → the objects in the connected Attio workspace. POST .../options/matching_attribute (body: { "context": { "attio_object": "people" } }) → the UNIQUE attributes on the chosen object, i.e. the ones Attio will accept as an upsert key. POST .../options/add_attributes_and_their_values (body: { "context": { "attio_object": "people" } }) → writable attributes on the chosen object, with the Attio `type`, multi-value flag and any `reference` token in `extras`. POST .../options/add_attributes_and_their_values (body: { "context": { "reference": "" } }) → the selectable values behind that token. Configure Action body: { "inputs": { "attio_object": "people", "matching_attribute": "email_addresses", "add_attributes_and_their_values": [ { "name": "email_addresses", "value": "{{input.work_email}}" }, { "name": "name", "value": "{{input.full_name}}" }, { "name": "job_title", "value": "{{enrich_1.title}}" } ] } } Field-by-field: - attio_object Object api_slug from the `attio_object` options call. - matching_attribute Attribute api_slug from the `matching_attribute` options call (unique attributes only). - add_attributes_and_their_values `[{name, value}]` — must include an entry whose `name` equals `matching_attribute`; that value is the lookup key. ================================================================================ 4. KEY NOTES ================================================================================ - **The matching attribute must be in the values list.** Attio looks the record up by the value it finds there; without it there is nothing to match on and the call fails. - An attribute the selected object does not have comes back as a `warnings[]` entry (`unknown_field`) from Configure Action, and the row is ignored at run time — check `warnings` after configuring rather than waiting for the run. - Only UNIQUE attributes can be the key — `options/matching_attribute` returns exactly that subset. Passing a non-unique attribute is a 400 from Attio. - On a match, the listed attributes are OVERWRITTEN (the same PUT semantics as attio_update_record), including multi-value ones. Attributes not listed are untouched. - Distinguish create from update with `created_at`: it is the record's original creation time, so a value older than this run means an existing record was matched. - The Attio connection must live on the API key's user account. If the connection lives under a different team member, Get Action Field Options returns a 424 — provision the API key from the user who owns the connection. - Composite attributes take a plain value: "ada@acme.com" for `email_addresses`, "acme.com" for `domains`. The nesting Attio's API expects is built for you. ================================================================================ 5. WHERE IT FITS IN A WORKFLOW ================================================================================ Pattern: enrichment -> attio_upsert_record (single-step idempotent sync into Attio, keyed on email or domain). ================================================================================ 6. WHEN TO USE ================================================================================ Use attio_upsert_record for idempotent sync when the object has a unique attribute to match on — it replaces the lookup + if/else + create/update chain with one step. ================================================================================ 7. WHEN NOT TO USE ================================================================================ The object has no unique attribute -> attio_lookup_record + workflow_if_else + attio_create_record / attio_update_record (https://floqer.com/docs/action-detail/attio_lookup_record.txt) You need to always create, duplicates included -> attio_create_record (https://floqer.com/docs/action-detail/attio_create_record.txt) ================================================================================ This file is maintained manually. Last updated: 2026-08-11. Full interactive reference: https://floqer.com/docs/reference Action catalog: https://floqer.com/docs/action-catalog.txt