> For the complete documentation index, see [llms.txt](https://docs.powerfulform.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.powerfulform.com/public-api/submissions/update-a-submission.md).

# Update a submission

Change a submission's tags, internal note and read status.

```
PATCH /submissions/{id}
```

Requires the `submissions:update` scope.

Three things can change on a stored submission: its **tags**, its **notes**, and whether it is **read**. Send any one of them, or all three.

## Request

```bash
curl -X PATCH https://app.powerfulform.com/api/public/v1/submissions/101 \
  -H "X-PFB-API-KEY: pfb_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
        "tags": ["wholesale", "follow-up"],
        "notes": "Called back on 17 Sep, sending a quote.",
        "status": "read"
      }'
```

<table><thead><tr><th width="150">Field</th><th width="110">Type</th><th>Notes</th></tr></thead><tbody><tr><td><code>tags</code></td><td>array</td><td>Tag <strong>names</strong>, up to 50. <strong>Replaces</strong> the existing tags.</td></tr><tr><td><code>notes</code></td><td>string</td><td>Up to 2000 characters. Send <code>null</code> to clear the note.</td></tr><tr><td><code>status</code></td><td>string</td><td><code>read</code> or <code>unread</code>.</td></tr></tbody></table>

An empty body is rejected with `422` — send at least one of the three.

## How tags behave

Tags are sent by **name**, not by id, so you never need a second request to look one up. A name that does not exist yet is created in your store automatically and then appears in the app's tag list like any other.

`tags` replaces the whole set rather than adding to it. To add one tag while keeping the rest, read the submission first and send the full list back:

```bash
# currently ["wholesale"] — add "follow-up" without losing it
curl -X PATCH https://app.powerfulform.com/api/public/v1/submissions/101 \
  -H "X-PFB-API-KEY: pfb_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "tags": ["wholesale", "follow-up"] }'
```

Sending `"tags": []` removes every tag from the submission.

{% hint style="info" %}
Tag names are matched exactly. `Wholesale` and `wholesale` become two separate tags, so pick one casing and keep your integration consistent with what the team types in the app.
{% endhint %}

## What cannot be changed

`content` is not editable, and there is no endpoint that edits it.

A submission is the record of what somebody sent at a moment in time. It has usually already been copied out to Google Sheets, Mailchimp, Klaviyo or your CRM the instant it arrived. Letting it be rewritten afterwards would leave two versions of the same event with no way to say which is right — so the record stays as submitted, and anything you learn later goes in `notes` or a tag.

To correct a genuine mistake, delete the submission and create a new one.

## Response

`200` with the full updated submission, in the same shape as [the submission object](/public-api/submissions.md#the-submission-object):

```json
{
  "data": {
    "id": 101,
    "form_id": 10,
    "status": "read",
    "content": { "name": "Le Thi Lan", "email": "lan@example.com" },
    "files": [],
    "tags": ["wholesale", "follow-up"],
    "notes": "Called back on 17 Sep, sending a quote.",
    "customer": null,
    "ticket": null,
    "is_hidden": false,
    "hidden_reason": null,
    "created_at": "2026-09-17T02:11:40Z",
    "updated_at": "2026-09-18T09:31:02Z"
  }
}
```

## Errors

<table><thead><tr><th width="120">Status</th><th width="230">Code</th><th>Cause</th></tr></thead><tbody><tr><td>403</td><td><code>insufficient_scope</code></td><td>The key is missing <code>submissions:update</code>. A read-only key cannot patch.</td></tr><tr><td>404</td><td><code>not_found</code></td><td>No such submission, or it belongs to another store.</td></tr><tr><td>415</td><td><code>unsupported_media_type</code></td><td>The body arrived without <code>Content-Type: application/json</code>.</td></tr><tr><td>422</td><td><code>validation_failed</code></td><td>An empty body, a note over 2000 characters, more than 50 tags, or a <code>status</code> other than <code>read</code> / <code>unread</code>.</td></tr><tr><td>429</td><td><code>rate_limited</code></td><td>The <strong>write</strong> bucket is spent — 60 per minute.</td></tr></tbody></table>

<br>

## Next steps

* [Submissions](/public-api/submissions.md) — read submissions and filter them by tag.
* [Delete submissions](/public-api/submissions/delete-submissions.md) — remove a record entirely.
* [View submissions](/submissions/view-submissions.md) — the same tags and notes, in the app.
