Set a transaction's category
well_set_transaction_categorySet ONE transaction's category — the write that clears a categorization gate.
REQUIRED: transaction_id, from well_list_uncategorized_window. category — the LABEL, exactly as that read returned it on the row's suggestion, or another label from the closed list this schema carries. The vocabulary is fixed: there is no free-text category and no way to mint one.
decision records HOW the category was chosen, and it changes what the row keeps.
accepted_classifier_suggestion— the user affirmed the label the classifier had already put on the row. The row keepscategory_source: "classifier"and its confidence score, and the affirmation is stamped ascategory_confirmed_at. Send this ONLY when the label equals the classifier's own stored suggestion.user_choice— the user picked the label themselves. The row recordscategory_source: "user"with no score.
The server verifies an accepted_classifier_suggestion claim against the row it is writing and downgrades it to user_choice when the stored suggestion is not that label, so the claim can never manufacture classifier provenance. Omitting decision is a user_choice.
A row from well_list_uncategorized_window never qualifies for the affirmation. That read returns rows carrying NO category at all, so there is no stored classifier value to affirm and the claim would be downgraded every time. Its categorySuggestions are PENDING proposals, not a stored category. Clearing that gate is always a user_choice; the affirmation exists for a surface that lists rows the classifier already categorized.
Categorizing a row does NOT move it in or out of the internal-transfer rule — that rule counts payment-means legs and no label affects it. What a category DOES change is exemption matching: an uncategorized row can never be matched by an exemption and always stays in a sum.
Send category: null to set the row back to no category. Use it when the user asks to remove or empty a transaction's category. The row then has no category, and the user owns that state: neither the classifier nor a counterparty rule fills it again. A null category takes no decision. "Uncategorised / suspense" is NOT "no category": it is a real category that books the line to the suspense account. Never send it to remove a category.
The server refuses a null category with the typed reason TRANSACTION_CATEGORY_BOOKED_IN_LEDGER when the row's category is already booked in the ledger. Tell the user the category is booked in the ledger, and offer to change it to another category instead.
One transaction per call. The rows are decided independently and each one is saved as the user decides it.
The list depends on the workspace. A personal space files household categories, a company workspace business categories, and both file the shared ones. A label outside the workspace's list writes nothing and returns refusal_reason with allowed_categories: send a label from that list.
A name that fits more than one label is a question, never a pick. When the words the person used fit two or more labels of the list (for example "Logiciels" or "software" fits both "Developer & engineering software" and "Business & productivity software"), do not call this tool: ask which one, naming each label that fits in the person's words, and call it once they answer. Never choose the nearer label, and never put two labels on one call.
confirm_first: true when the person's message asks that nothing change before they approve (for example "ne modifie rien avant mon accord", "show me first", "wait for my OK"). Omit it otherwise. In Well's own sessions the call then waits on Well's confirmation card, even when the person lets Well act alone for this kind of change. In another assistant connected to Well with the person's own sign-in, Well shows no card and a flagged call changes nothing: it returns awaiting_confirmation: true. Show the person the transaction and the label, ask for their OK in the conversation, then call again without the flag. Without the flag, your host's own approval of the call is the confirmation. Well checks that the person is signed in and a member of the workspace, and that the label is a category of this workspace. A connection made with an API key cannot change a category.
This write changes Well's copy of the transaction only. The bank or tool the row was synced from keeps its own category: no call reaches it. When the person named that bank or tool, say that it stays unchanged.
When the token authorizes one workspace, call this directly — no workspace call is needed first. When it authorizes several, this read will not guess which one you mean: pass workspace_id on the call.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| category | Yes | The category label to store, one of the labels in this list. null sets the row back to no category. | |
| decision | No | How the user arrived at the label. Omit for a user choice. See the description before sending accepted_classifier_suggestion. | |
| workspace_id | No | Target workspace. Omit when the token authorizes one workspace. Required when it authorizes several — a write lands in exactly one workspace and this call would not say which. | |
| confirm_first | No | True when the person's message asks that nothing change before they approve. In Well's own sessions the call then waits on Well's card. Elsewhere it changes nothing and returns awaiting_confirmation: ask the person in the conversation, then call again without it. Omit otherwise. | |
| transaction_id | Yes | The transaction to categorize, from well_list_uncategorized_window. | |
| conversation_id | No | The conversation id returned by the previous Well result, in its meta under well/conversation_id, in its structuredContent, or in its JSON text block. Pass it back on every call in the same conversation, including a call a card makes, so the chosen workspace and the earlier answers still apply. It decides the conversation on its own: nothing the host states about the session replaces it. Omit it only on the first call of a conversation. | |
| idempotency_key | No | Optional client-supplied key. A retried write with the same key returns the original result instead of re-applying the operation. | |
| workspace_scope | No | Restrict this call to the family: the token's primary workspace plus the company workspaces under it that you are a member of. Unrelated authorized workspaces drop out of the read; row reads merge across the family, while a per-workspace figure still reports exactly one workspace. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| error | No | ||
| success | Yes | ||
| category | No | The label stored on the row after the write. | |
| error_code | No | The typed reason of a refusal, when the server gave one. "TRANSACTION_CATEGORY_BOOKED_IN_LEDGER": the category is booked in the ledger, so it cannot be set back to no category. | |
| refusal_reason | No | Set when the category is not in this workspace's list. Nothing was written. | |
| transaction_id | No | ||
| category_source | No | Provenance the server settled on: "classifier" when it accepted the affirmation claim, "user" when the caller picked the label or the claim was downgraded. | |
| conversation_id | No | The conversation this result belongs to. Pass it back as the conversation_id argument on every later Well call in the same conversation. | |
| newly_connected | No | Tools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. The connected-line rule says when to tell an entry; when it does, one line per entry, in the person's language: "<name> is connected.". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later. | |
| allowed_categories | No | With refusal_reason: the categories this workspace files and is offered. Send `label` back; `name` is how the workspace shows it. | |
| category_confidence | No | The classifier's score, preserved only on an accepted affirmation. Null on a user choice. | |
| conversation_id_note | No | Present only when the server opened a fresh lane, stating that no choice recorded earlier was read. | |
| awaiting_confirmation | No | True when the call asked to wait for the person's approval and nothing was changed. | |
| conversation_id_source | No | Where the conversation id came from: the host's own request meta, the caller's argument, or a fresh lane the server opened. |