Custom Integrations Feature request (2 of 2): Create and delete records in Custom Integration databases
This request builds on Request 1, which asks for writable fields and their
executecallback, today an undocumented path behind the Jira integration’s beta, to become a supported part of the Custom Integration API: Custom Integrations Improvement 1 - Officially support writable fields
Summary
Request 1 covers editing synced records from Fibery. Creating and deleting them has no path at all, documented or not: declaring create or delete actions alongside update is silently ignored (O1). The only workaround, an external Action, runs outside the sync and costs about 1.4 s per record.
I’m asking for opt-in creation and deletion, delivered through the same execute callback that carries edits (Request 1), with the outside system’s ID handed back on create. The integration keeps owning all sync logic. Fibery reports the change, waits for the answer, and records the outside ID.
| # | Change |
|---|---|
| B1 | Opt-in creation, with the outside system’s ID handed back |
| B2 | Opt-in deletion |
| B3 | Document today’s deletion rules |
The end goal
Request 1 describes the finished state in full, including a walk through one record’s life (“The end goal”). This request adds:
- People create and delete records in synced databases, where the integration allows it: from any view, form, import, template or automation, or through the API.
- A new record shows as pending until the outside system confirms it and Fibery stores its outside ID. Links to other pending records resolve once those are created. A record that can’t be created stays, marked failed, with Retry and Discard.
- A deleted record is removed only once the outside system agrees. If it refuses, the record comes back with the reason. If it archives instead, the record stays with its archived values.
- The integration still owns the rules: what’s required, what can be deleted, and how the outside system’s IDs are assigned.
Changes in detail
B1. Opt-in creation
A type declares create in its sync config, next to the update action that turns on writable fields (Request 1). Its database then allows new records everywhere native databases do: views, forms, imports, duplicating, templates, automations and the API. Fibery sends each new record’s Fibery ID and values to execute:
{ "action": { "create": { "task": [
{ "fiberyId": "6f1c…", "fields": { "name": "New task", "statusId": { "id": "s-open", "name": "Open" } } }
] } } }
The integration replies with the outside system’s ID, and optionally the record’s final values. Fibery stores the ID as the record’s fibery/sync-id, so later syncs match it:
{ "create": { "task": [ { "fiberyId": "6f1c…", "id": "t-42", "fields": { "number": "T-0042" } } ] } }
Until the ID arrives, the record is pending. An error reply marks it failed, with the message (Request 1, A3 and A6). The callback shape and the slot for the ID already exist (O2, O3).
B2. Opt-in deletion
A type declares delete, and its records can then be deleted by people, automations and the API (O1). Fibery sends the outside IDs to execute:
{ "action": { "delete": { "task": [ { "id": "t-2" } ] } } }
A success reply confirms the delete, and an error reply restores the record and shows the message. For outside systems that archive rather than delete, the reply can keep the record with new values:
{ "delete": { "task": [ { "id": "t-2", "keep": true, "fields": { "active": false } } ] } }
B3. Document today’s deletion rules
Document the full-versus-delta rules in O4, including that __syncAction must be declared in the schema for REMOVE to work.
Background: what I observed
These come from the same probe and workspace as Request 1.
O1. Declaring create or delete is silently ignored
With create, update and delete all declared, about nine minutes of active UI use produced six execute calls, all of them updates. Fibery showed no error, and synced databases offered no way to create or delete records.
Creating from Fibery therefore takes an external Action, as Jira does with add_issue. Each run costs about 1.4 s of Fibery overhead, even when the integration answers in about 1 ms, and the new record appears only at the next sync.
O2. execute is already a general dispatch endpoint
An external Action declared with sync: {"action": "refresh"} doesn’t start a sync. Instead, Fibery POSTs the merged reply data to execute under the action’s name: {"action": {"refresh": {"touched": [1, 1]}}}. So execute already carries arbitrary action names, and create and delete fit its shape.
O3. Fibery already stores each record’s outside ID
Records carry fibery/sync-id (for example "t-3"), and each relation’s outside IDs sit in hidden text fields. The slot a create needs to fill already exists.
O4. Deletes from the integration depend on the sync type
| Sync type | Record left out | Field left out | {"id": …, "__syncAction": "REMOVE"} |
|---|---|---|---|
| Full | deleted | emptied | not a delete: the record is blanked |
| Delta | kept | kept | deletes the record, but only if the schema declares a __syncAction field; otherwise the record is blanked |
Under a full sync, a record created in Fibery but not yet confirmed would be deleted unless it’s protected (see Hard parts).
Hard parts, and how I’d solve them
On Fibery’s side
- A full sync would delete a pending record (O4). A record without a
fibery/sync-idis pending, and full syncs never delete pending records. - The outside system is slow to return an ID. Let the create reply omit the
id, so the record stays pending, and accept the ID later through the webhook intake or a sync, as{"fiberyId": "6f1c…", "id": "t-42"}. - Edits while pending. Hold them in the record’s queue (Request 1, A7) until the ID is known, or send them keyed by
fiberyId. - Links to pending records. Someone creates a customer, then a job linked to it. Send the link with the customer’s Fibery ID, as
{"fiberyId": "…", "id": null, "name": "…"}, and deliver creates in the order they were made. - Duplicates on retry. The
fiberyIdis the idempotency key, reused on every retry. - A create that finally fails. Keep the record, marked failed with the message, with Retry and Discard, so nothing the user typed is lost.
- Every way of creating a record. Forms, imports, duplicating, templates, automations, the API and “add new” in a relation field all use the same
createcall. Bulk creates arrive batched, with a result per record, so one rejection doesn’t fail the rest. - Required and generated fields. The integration rejects incomplete records with a message, and returns generated values in its reply. Optionally, a schema flag lets Fibery check required fields before sending.
- Records the outside system creates in one call, such as an invoice and its line items. Fibery creates them one at a time. The integration can reply without an ID, holding the invoice as pending until its lines arrive. Or it can wait for a Send button, through an external Action or an HTTP request automation, and create everything in one call (Request 1, “Does every edit have to sync immediately?”).
- Trash, cascades and linked records. Restoring from trash sends a
create, or is blocked for integration records. A cascade sends each delete. If the outside system refuses a delete, for example for a customer with invoices, the error reply restores the record. - Undo. Undoing a create sends a delete, and undoing a delete sends a create.
- Permissions. Fibery’s permissions decide who can create and delete, including protecting records the outside system treats as final, such as a billed invoice. The integration can still refuse.
On the integration’s side
The integration keeps the map from fiberyId to outside ID, creates dependent records in order, enforces the outside system’s rules (required fields, uniqueness, records that can’t be deleted), archives where the outside system works that way, replies quickly and supplies slow IDs later, and resolves conflicts.
Anticipated questions
Is this a sync engine? No. Fibery delivers each create or delete once, waits for the answer, and records the ID. Mapping, conflicts and source-of-truth decisions stay in the integration.
Why not keep using Actions? They’re slow and run outside the sync (O1).
Why not use the regular API? It can create and delete, but a sync built on it gives up read-only fields and the managed schema (Request 1, O10).
Won’t this multiply calls? It’s one call per created or deleted record, with bulk operations batched. That’s fewer than today’s workaround, which needs an Action call per record plus a sync.
What about integrations that don’t opt in? Nothing changes for them.
Out of scope
- Everything in Request 1, which this request assumes.
- A native bi-directional sync engine, field mapping, or conflict resolution.
Open questions I couldn’t answer from outside
- Is there an internal reason synced databases can’t create records, such as
fibery/sync-idbeing required at creation? - Does Fibery match a synced record to an existing one only by
fibery/sync-id? - Should pending records be visible to everyone, or only to their creator, until confirmed?
Appendix: test setup
This uses the same probe as Request 1. The create/delete declaration test (O1) and the deletion rules (O4) are from 2026-09-07, and the fibery/sync-id observation (O3) is from 2026-10-31.