Run a query or mutation directly
Reach for a dedicated action below when one exists: it gives you a real form to fill in instead of a hand-written query, and it already accounts for the behaviors described on this page. Run GraphQL Query is the fallback for anything a dedicated action doesn’t cover.
Set a custom attribute’s value
Nine actions set one custom attribute’s value on one record. Each takes a Connection, the record’s numeric ID, the attribute’s Key, a Value, and an Etag, and returns the updated attribute.
Leave Etag blank to create an attribute that doesn’t exist yet.
These actions set an attribute’s value. Which attributes exist on an entity type at all is separate, org-level configuration. Read it with Get Organization (under
settings.<entity>.attributes) and change it with the two actions below.
Update Run Step Attribute only works while the run step is in REDLINE status; every other status rejects the write. Put the step into redline, set the attribute, then submit and approve the redline to make the step workable again.
Configure which attributes exist
Two actions change an entity type’s attribute schema, which attributes exist and what type they are, not any one record’s value.
Leave Options blank to leave an attribute’s existing choices alone. These actions send nothing for that field when it’s blank, rather than an empty list, so an untouched field can never wipe out a live attribute’s options.
Get, create, update, and delete records
Search and list records
These twelve actions share the same conventions:
- Every typed filter is an exact match. Fill in a field and it becomes an exact-match filter; leave it blank and it’s left out, so it never narrows the search. Date fields come as After/Before pairs.
- Additional Filters is a JSON field for anything the typed filters don’t cover, such as partial matches or filtering on a related record. A key you set there overrides the matching typed filter.
- Max Results (default 100) caps how many records come back. Without a cap, a broad search could return an entire catalog in one step’s output. List Rules has no such cap, since the number of rules an organization has is naturally bounded.
- Sort (blank means oldest-first by ID) sets the row order, picked from a live list of that record type’s sortable fields. See Sort your results safely for what it does and doesn’t guarantee.
Max Results keeps the OLDEST N by default, not the newest. Set Sort to
_CREATED_DESC (or ID_DESC) to cap the newest N instead. A _DESC on any other field only reverses that field’s own order. For “everything that changed since my last run,” filter on Created After or Updated After instead of sorting; it needs no multi-page read at all, which matters most on Get User Notifications, since that feed only ever grows.Locations, Teams, and Units Of Measurement each also back a dropdown elsewhere in this component, separate from their List action here: the dropdown is for picking one value on another action’s field, while the List action returns full records for your flow to use. You’ll likely use both, for different purposes.
How inputs behave
A few conventions apply across most actions on this page:- Blank means “leave alone.” An optional field you don’t fill in is left out of the update entirely, so it never clears an existing value. The one exception is Attribute Value on the attribute actions above: there, blank clears the attribute, since setting its value is the entire point of those actions.
- Yes/No fields have a third option: “leave unchanged.” These render as a dropdown rather than a toggle, specifically so an untouched field doesn’t get sent as an explicit “No” and overwrite an existing value.
- Additional Fields is a JSON field on most create and update actions, for any field this page’s typed inputs don’t expose. A key you set there overrides the matching typed field. A handful of actions don’t have this field at all: those are the ones whose typed inputs already cover every field ION accepts.
- Custom attributes can only be set on create, not on update. Create actions take an Attributes field. To change an attribute afterward, use that entity’s own Update Attribute action (in Set a custom attribute’s value above) instead of its Update action.
- Etags. Every update and delete action requires the record’s current etag. Read it from the matching Get or Search action immediately beforehand; an out-of-date etag fails the step with a concurrency error.
- Values are checked, not guessed at. An ID must be a whole number, a date must be a real date, and a Yes/No field must be an actual yes or no. Each fails the step with a clear message rather than silently being reinterpreted into something ION happens to accept.
Things to know before you build
File attachments are rejected on a run that’s already complete
Create File Attachment fails if the run it’s attaching to has already reached Complete status. There’s no override. Attach the file while the run is still open, or reopen the run first if you need to attach one afterward.A status change that’s accepted isn’t always a status change that happened
Update Run Step, Update Purchase Order, and Update MBOM can each report success while the record’s status doesn’t actually move: an approval rule or validator can silently refuse the transition. All three actions check the record’s status after the call and fail the step by name if it didn’t change as asked. Update Run Step and Update Purchase Order also return the statuses each record can move to next, so you can check what’s valid before attempting a transition.Some deletes are deliberately not exposed
ION’s API can delete more record types than this component exposes. Deleting a supplier, a purchase order, or an entire mBOM outright is left out on purpose: each is destructive to master data, a financial record, or an entire bill of materials, and the judgment was that this class of delete should happen in ION’s own UI, where the consequences are visible, rather than from an unattended flow. Use Run GraphQL Query if you deliberately need one of these.A part kit’s items can’t move between kits
There’s no action that reparents a kit item to a different kit. To move one, delete it from its current kit with Delete Part Kit Item and re-create it on the other with Create Part Kit Item.Get ABOM Installation needs two IDs
Unlike every other Get action on this page, Get ABOM Installation is identified by a pair of IDs, the build requirement and the part inventory record, rather than one. An as-built installation doesn’t have a single-column identity of its own: it’s defined by which inventory went into which build requirement.Sort your results safely
Every List and Search action’s Sort input appends the record’s ID as a tiebreaker automatically, in the same direction you picked. This makes tied rows come back in a consistent order, but it does not make every sort safe across a multi-page read: only the default (blank, oldest-first by ID) guarantees that a record created while your flow is still reading won’t be skipped or duplicated. A non-default sort is safe on a single page (Max Results at 100 or below) or on data nothing is actively changing. For “everything that changed since my last run” over an actively-changing set of records, filter on Created After or Updated After instead of changing Sort.Reading Run GraphQL Query’s output
Run GraphQL Query doesn’t fail the step when ION returns a GraphQL error. It always succeeds, so your flow can inspect the error and decide what to do next rather than the step aborting outright. The response places the query’s own data at the top level of the output, alongside two extra fields:errors and extensions.
A successful query has errors set to nothing:
errors, each with a code you can branch on, for example, refetching a record’s latest etag and retrying on a concurrency error, or surfacing the message to whoever’s watching the flow on a validation error: