# Custom Integrations Improvement 2 - Allow creates and emit posts for creates and deletes

**URL:** <https://community.fibery.io/t/custom-integrations-improvement-2-allow-creates-and-emit-posts-for-creates-and-deletes/11483>\
**Category:** Ideas & Features\
**Created:** [November 1, 2026, 3:03am UTC](https://community.fibery.io/t/custom-integrations-improvement-2-allow-creates-and-emit-posts-for-creates-and-deletes/11483 "2026-11-01T03:03:13Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tommy\_Hedley](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/tommy_hedley/32/6468_2.png) [@Tommy\_Hedley](https://community.fibery.io/u/Tommy_Hedley)\
**Post date:** [November 1, 2026, 3:03am UTC](https://community.fibery.io/t/custom-integrations-improvement-2-allow-creates-and-emit-posts-for-creates-and-deletes/11483/1 "2026-11-01T03:03:13Z")

</div>

# 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 `execute` callback, 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](https://community.fibery.io/t/custom-integrations-improvement-1-officially-support-writable-fields/11482)

## 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`:

```json
{ "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:

```json
{ "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`:

```json
{ "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:

```json
{ "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-id` is 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 `fiberyId` is 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 `create` call. 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

1. Is there an internal reason synced databases can’t create records, such as `fibery/sync-id` being required at creation?
2. Does Fibery match a synced record to an existing one only by `fibery/sync-id`?
3. 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.
