Replace a module’s field annotations
const url = 'https://api.sloose.com/orgs/org_9f3c/config/fields/accounts/annotations?connector=con_8f2a';const options = { method: 'PUT', headers: { 'If-Match': '"7"', Authorization: 'Bearer <token>', 'Content-Type': 'application/json' }, body: '[{"apiName":"example","description":"example","format":"example","examples":["example"],"aliases":["example"],"excludeFromAi":true,"derived":true,"defaultMapping":{"mode":"column","source":"example","staticValue":"example","staticPickedIn":{"connection":"example","module":"example","id":"example","name":"example"},"transform":"example","skip":true,"searchField":"example","searchMethod":"example","searchExpression":"example","patch":{"when":["pending"],"overwrite":"always"},"files":{"sheet":"example","holds":"name","separator":"example"},"key":true,"keyMethod":"example","keyExpression":"example","onNone":"empty","onSeveral":"ask"},"excluded":true,"requiredForImports":"waivable","writtenAs":"upper","mustBe":{"rule":"example","says":"example"}}]'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url 'https://api.sloose.com/orgs/org_9f3c/config/fields/accounts/annotations?connector=con_8f2a' \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --header 'If-Match: "7"' \ --data '[ { "apiName": "example", "description": "example", "format": "example", "examples": [ "example" ], "aliases": [ "example" ], "excludeFromAi": true, "derived": true, "defaultMapping": { "mode": "column", "source": "example", "staticValue": "example", "staticPickedIn": { "connection": "example", "module": "example", "id": "example", "name": "example" }, "transform": "example", "skip": true, "searchField": "example", "searchMethod": "example", "searchExpression": "example", "patch": { "when": [ "pending" ], "overwrite": "always" }, "files": { "sheet": "example", "holds": "name", "separator": "example" }, "key": true, "keyMethod": "example", "keyExpression": "example", "onNone": "empty", "onSeveral": "ask" }, "excluded": true, "requiredForImports": "waivable", "writtenAs": "upper", "mustBe": { "rule": "example", "says": "example" } } ]'Sets the whole annotation set for the module. An annotation is how an organisation teaches Sloose its own vocabulary: a friendlier label, a hint, whether the field is excluded from AI (which decides whether a sample can ever reach the model).
Every field named must be one the module has. A field the CRM no longer returns is one it has: the module page keeps it on purpose, because an older template may still name it, and its annotation is written like any other. A field the module never had refuses the whole set (422, code: UNKNOWN_FIELDS), and nothing is written: 422 because the body names it, where the one-field route, whose path names the field, answers 404. That is asked before the write and again inside it, since removing a gone module deletes its fields.
What the set leaves out is cleared, on fields the CRM still returns. A departed field left out keeps its annotation: a repository written before the field left does not know it.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The organisation id the session was issued for. A token for one organisation can never read another.
Example
org_9f3cThe organisation id the session was issued for. A token for one organisation can never read another.
The module’s key or CRM API name — either is accepted.
Example
accountsThe module’s key or CRM API name — either is accepted.
Query Parameters
Section titled “Query Parameters”The connection this is about, by id: one of the organisation’s, or your own. REQUIRED: absent or empty is 400 CONNECTION_REQUIRED, listing the connections this bearer may name, because nothing picks one for a request that does not say (design §14.8). Any other — another organisation’s, or another person’s — is 404 CONNECTION_NOT_FOUND.
Example
con_8f2aThe connection this is about, by id: one of the organisation’s, or your own. REQUIRED: absent or empty is 400 CONNECTION_REQUIRED, listing the connections this bearer may name, because nothing picks one for a request that does not say (design §14.8). Any other — another organisation’s, or another person’s — is 404 CONNECTION_NOT_FOUND.
Header Parameters
Section titled “Header Parameters”The registryVersion this change was made against, as "7" or 7 — a weak tag (W/"7") is refused, since If-Match uses strong comparison. Sent, the write is refused with 409 (code: REGISTRY_CONFLICT, the current version in the body) when the organisation has moved since, and otherwise answers the version it made: one past the version sent for a write made in one transaction, or the version sent itself for a request that asks for no change (an empty PATCH /config/writing), since it makes none. A bundle (POST /config/bundle) is several transactions and only its first waits on this version: it answers the version its own bumps took the organisation to — each part bumps only when it writes something, so a push of what is already there answers the version sent — and none — nor an etag — when another write landed between them; one landing after them, while its templates are saved, withholds the etag alone. Omitted, there is no condition, and * is no condition either — and a write with no condition answers no registryVersion (nor, from a bundle, an etag), since nothing says which version it was made from. A value that is neither is 400 (code: BAD_IF_MATCH) rather than ignored — a precondition silently dropped looks like conflict detection and is not.
Example
"7"The registryVersion this change was made against, as "7" or 7 — a weak tag (W/"7") is refused, since If-Match uses strong comparison. Sent, the write is refused with 409 (code: REGISTRY_CONFLICT, the current version in the body) when the organisation has moved since, and otherwise answers the version it made: one past the version sent for a write made in one transaction, or the version sent itself for a request that asks for no change (an empty PATCH /config/writing), since it makes none. A bundle (POST /config/bundle) is several transactions and only its first waits on this version: it answers the version its own bumps took the organisation to — each part bumps only when it writes something, so a push of what is already there answers the version sent — and none — nor an etag — when another write landed between them; one landing after them, while its templates are saved, withholds the etag alone. Omitted, there is no condition, and * is no condition either — and a write with no condition answers no registryVersion (nor, from a bundle, an etag), since nothing says which version it was made from. A value that is neither is 400 (code: BAD_IF_MATCH) rather than ignored — a precondition silently dropped looks like conflict detection and is not.
Request Bodyrequired
Section titled “Request Bodyrequired”object
object
object
object
object
object
Responses
Section titled “Responses”Applied. Counts of what changed are included.
object
The version the organisation is at after this write, to send as the next write’s If-Match: one past the version you sent in If-Match for a write made in one transaction (a bundle, several, answers the version its own bumps took the organisation to, or none when another write landed between them), or that version itself for a request that asks for no change (an empty PATCH /config/writing, which writes nothing and makes no version; sending the value the organisation already has still writes, and moves it). Only a write sent with a version in If-Match answers one. Without (no header, or *), the write lands on whatever version the organisation is at, and nothing on the server knows which version your picture of the configuration was built from: another administrator’s change may be inside the number, and sent back as If-Match it would let your next write overwrite that change unseen. So it is left out. To write again, read the configuration first (its GET answers the version), or send If-Match.
Example
{ "ok": true}The request — its body or its query — did not match the schema (issues carries the Zod issue list), or: The request named no connection (code: CONNECTION_REQUIRED, with connections: the ones this bearer may name). Nothing picks one for a request that does not say (design §14.8).
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}No bearer, or one that no longer resolves: a session that is unknown or expired (code: AUTH_REQUIRED), or an API token that was revoked or expired (TOKEN_REVOKED, TOKEN_EXPIRED), whose organisation is gone (ORG_NOT_FOUND) or whose member or user row is (MEMBERSHIP_GONE).
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}The bearer’s role is too low (code: ROLE_REQUIRED), or it was issued for a different organisation; the organisation has been closed (code: ORG_CLOSED, either kind of bearer); the person is banned (code: BANNED, a session); or it is a session that is signed in but in no organisation (code: NO_ORG): one that never joined one, or whose person was taken out of the one it was in, or left it. Signing in again changes nothing for NO_ORG; choosing or making an organisation does.
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}No such module or connection, or it is not visible to this session.
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}The organisation’s configuration has changed since the version in If-Match; the current one is in the body.
object
Example
{ "code": "REGISTRY_CONFLICT"}A field the module has no row for (code: UNKNOWN_FIELDS, each named in missing), a case its kind does not take (code: WRITTEN_AS_NOT_FOR_KIND, each named in fields with its kind and the cases it takes: a website takes none, an email lower case only), or a Must be rule that reads anything but the value, your helpers and plain built-ins (code: INVALID_RULE, each named in fields with the rule and why). Nothing was written.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
WRITTEN_AS_NOT_FOR_KIND: each field given a case its kind does not take. INVALID_RULE: each field given a Must be rule that reaches past the value, and why.
object
The field’s kind, as discovery last read it.
The cases this kind takes: none for a website, lower for an email.
object
What the rule reaches that it may not, in words.
Example
{ "fields": [ { "writtenAs": "upper", "takes": [ "upper" ] } ]}The restore switch is on (code: MAINTENANCE): every route but /health and /robots.txt is refused before anything is read, except the operator’s own POST /staff/people/{id}/delete with the ADMIN_TOKEN. Sloose is down for maintenance. Please try again in a few minutes.
object
Example
{ "code": "MAINTENANCE"}Headers
Section titled “Headers”Seconds until asking again is worth it (300 while the switch is on).