Inbound pattern: receiving data into Attio
The inbound pattern starts a workflow from an external HTTP request and writes the result into your CRM. Use it whenever another system pushes data to Attio: form submissions, product events, partner leads, and enrichment callbacks. The flow runs in this order:- Webhook received fires when the external system posts JSON to the workflow’s webhook URL.
- Parse JSON converts the raw payload body into typed variables.
- Filter drops payloads that fail validation before any write happens.
- Create or update record upserts the person or company. An upsert updates a matching record if one exists, or creates a new one if it does not.
- Add record to list places the new record on the inbound list its owner watches.
email or domain until Parse JSON has turned that string into structured outputs. Always run the filter before the first write. The trigger fires on whatever the external system sends, including malformed or test payloads.
For example, a marketing form posts { "email": "jane@acme.com", "company_domain": "acme.com", "source": "webinar" }. Parse JSON exposes email, company_domain, and source as variables. The filter keeps only rows where email is not empty. Create or update record upserts a person on jane@acme.com. Add record to list then drops that person onto your inbound-leads list for routing.
Outbound pattern: calling external systems from Attio
The outbound pattern reaches into another system when it holds the data or action a workflow needs. Use it to enrich a record from a provider, post to an internal service, or trigger a downstream job. To enrich a record means to fill in missing details, such as a company’s size or industry, from an outside source. The flow runs in this order:- A trigger fires. This is often Record created or an Attribute value changed event.
- Filter confirms the call is worth making, for instance that a company domain exists.
- Send HTTP request calls the external URL and returns a status code, a response body, and a success flag.
- Parse JSON extracts the fields you need from the response body.
- Update record writes the returned values back to the record.
acme.com triggers the workflow. The filter checks that the domain attribute is set. Send HTTP request calls your enrichment provider’s API with that domain. Parse JSON reads employee_count and industry from the response, and Update record writes both onto the company.
JSON schema advice
Parse JSON needs a schema before it can produce typed variables. A schema is the list of field names and their types that the block expects to find. This is where most integrations succeed or fail. A few habits keep it predictable.1
Generate the schema from a real payload
Paste a representative payload into Parse JSON and let it generate the schema. A captured production sample reflects the field names, casing, and nesting the provider actually sends. A hand-written schema rarely does. For instance, use one real webhook delivery from
jane@acme.com’s form submission.2
Mark optional fields as optional
Flag any field that the source may omit as optional. Missing optional values return empty rather than failing the block, so a record that lacks a phone number still flows through.
3
Keep IDs as strings
Use the string type for identifiers unless you genuinely need number math on them. A long numeric ID parsed as a number can lose precision or pick up unwanted formatting. As a string it round-trips intact.
4
Parse only the fields the workflow uses
Extract just the fields a later block reads. A leaner schema is faster to reason about. It is also less likely to break when the provider adds or renames fields you never touch.
5
Filter before any write
Follow Parse JSON with a Filter before writing anything. A type mismatch fails the parse block outright. But a present-and-wrong value, such as an empty email or a placeholder domain, passes parsing. Only a filter will stop it from reaching a record.
Timeout and failure behavior
Send HTTP request has a two-minute timeout, and any external call can fail, stall, or return a partial response. Design every outbound call as if the other system is unreliable, because eventually it is. Three checks keep a flaky integration from corrupting your data:- Inspect the success flag first. Send HTTP request returns whether the response was successful alongside the status code. Branch on that flag before you touch the response body.
- Parse only on success. Run Parse JSON against the response body only when the call succeeded. Parsing an error page or an empty body fails the block or, worse, yields garbage values.
- Hold customer-visible writes until the response is complete. If a response is partial, skip the write. Do not stamp half-enriched data onto a record a rep is about to read.
When to graduate to a custom block
The HTTP pattern is the right tool for a one-off integration or a simple payload. It also fits while you are still checking whether a workflow is worth building. The manual pattern stops scaling once the same HTTP call appears across many workflows. It also stops scaling once non-technical operators need to configure it. At that point, consider building a typed, reusable block instead. See App SDK custom blocks for the trade-off.See also
Source: Attio Workflows block library. Last reviewed against the Attio Help Center, June 2026.