This page lists the 40 endpoints that src/cluster_erp/server/routes/ defines and create_app includes directly (src/cluster_erp/server/app.py:1433-1440). They are not part of a module, so no require_app dependency is attached at this mount. The same folder holds currencies.py, which the currencies module mounts, and signup.py and vendor.py, which are documented on System endpoints. The mechanism behind these routes is explained in Shared server routes.
Group facts¶
| Item | Value | Source |
|---|---|---|
| Base paths | /api/v1/notes, /api/v1/attachments, /api/v1/email, /api/v1/chat, /api/v1/parties, /api/v1/{module}/_fields, /api/v1 |
router definitions listed in the section Endpoint summary |
| Endpoints | 40, counted from the route decorators in the seven files | src/cluster_erp/server/routes/ |
| Authentication | Bearer header or session cookie; see Authentication and headers | src/cluster_erp/modules/auth/guards.py:85-167 |
| Permission guard | 39 of 40 routes declare require_permission; GET /api/v1/_overlay depends on get_current_user |
src/cluster_erp/server/routes/tenant_fields.py:446-449 |
| Error format | See Errors | src/cluster_erp/server/error_handler.py:33-46 |
Endpoint summary¶
One row per file in src/cluster_erp/server/routes/ that create_app includes.
| File | Routers | Endpoints | Router source |
|---|---|---|---|
notes.py |
router (/api/v1/notes) |
6 | src/cluster_erp/server/routes/notes.py:14 |
attachments.py |
router (/api/v1/attachments) |
8 | src/cluster_erp/server/routes/attachments.py:27 |
email.py |
router (/api/v1/email) |
3 | src/cluster_erp/server/routes/email.py:22 |
chat.py |
router (/api/v1/chat) |
1 | src/cluster_erp/server/routes/chat.py:23 |
party_composite.py |
router (/api/v1/parties) |
1 | src/cluster_erp/server/routes/party_composite.py:27 |
party_roles.py |
router (/api/v1/parties) |
3 | src/cluster_erp/server/routes/party_roles.py:31 |
tenant_fields.py |
router (/api/v1/{module}/_fields), overlay_router (/api/v1) |
18 | src/cluster_erp/server/routes/tenant_fields.py:42, src/cluster_erp/server/routes/tenant_fields.py:43 |
Notes endpoints¶
Notes attached to any record by entity type and id. Each route also checks the read code of the parent entity through _assert_parent_readable (src/cluster_erp/server/routes/notes.py:17-29).
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
GET |
/api/v1/notes/{entity_type}/{entity_id} |
list_notes |
note.read |
none | none | list[NoteRead] |
200 (default) | src/cluster_erp/server/routes/notes.py:33 |
GET |
/api/v1/notes/count/{entity_type}/{entity_id} |
count_notes |
note.read |
none | none | dict |
200 (default) | src/cluster_erp/server/routes/notes.py:46 |
POST |
/api/v1/notes/ |
create_note |
note.create |
NoteCreate |
none | NoteRead |
201 |
src/cluster_erp/server/routes/notes.py:59 |
PUT |
/api/v1/notes/{note_id} |
update_note |
note.update |
NoteUpdate |
none | NoteRead |
200 (default) | src/cluster_erp/server/routes/notes.py:71 |
POST |
/api/v1/notes/bulk-delete |
bulk_delete_notes |
note.bulk_delete |
BulkDeleteRequest |
none | BulkDeleteResponse |
200 (default) | src/cluster_erp/server/routes/notes.py:89 |
DELETE |
/api/v1/notes/{note_id} |
delete_note |
note.delete |
none | none | none | 204 |
src/cluster_erp/server/routes/notes.py:104 |
Attachments endpoints¶
File attachments of any record: upload, count, download, list, replace the file, update, bulk deactivate, and deactivate. Each route also requires the read permission of the parent entity (src/cluster_erp/server/routes/attachments.py:29-57).
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
POST |
/api/v1/attachments/ |
upload_attachment |
attachment.create |
multipart entity_type, entity_id, description, file |
none | AttachmentRead |
201 |
src/cluster_erp/server/routes/attachments.py:62 |
GET |
/api/v1/attachments/count/{entity_type}/{entity_id} |
count_attachments |
attachment.read |
none | none | dict |
200 (default) | src/cluster_erp/server/routes/attachments.py:88 |
GET |
/api/v1/attachments/{attachment_id}/download |
download_attachment |
attachment.download |
none | none | Response |
200 (default) | src/cluster_erp/server/routes/attachments.py:102 |
GET |
/api/v1/attachments/{entity_type}/{entity_id} |
list_attachments |
attachment.read |
none | none | list[AttachmentRead] |
200 (default) | src/cluster_erp/server/routes/attachments.py:124 |
PUT |
/api/v1/attachments/{attachment_id}/replace |
replace_attachment_file |
attachment.update |
multipart file |
none | AttachmentRead |
200 (default) | src/cluster_erp/server/routes/attachments.py:138 |
PUT |
/api/v1/attachments/{attachment_id} |
update_attachment |
attachment.update |
AttachmentUpdate |
none | AttachmentRead |
200 (default) | src/cluster_erp/server/routes/attachments.py:165 |
POST |
/api/v1/attachments/bulk-delete |
bulk_delete_attachments |
attachment.bulk_delete |
BulkDeleteRequest |
none | BulkDeleteResponse |
200 (default) | src/cluster_erp/server/routes/attachments.py:184 |
DELETE |
/api/v1/attachments/{attachment_id} |
delete_attachment |
attachment.delete |
none | none | none | 204 |
src/cluster_erp/server/routes/attachments.py:202 |
E-mail endpoints¶
Recipient resolution, sending records by e-mail, and sending a free e-mail.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
POST |
/api/v1/email/resolve |
resolve_emails |
email.send |
EmailResolveRequest |
none | EmailResolveResponse |
200 (default) | src/cluster_erp/server/routes/email.py:95 |
POST |
/api/v1/email/send-records |
send_records |
email.send |
EmailSendRecordsRequest |
none | EmailSendResponse |
200 (default) | src/cluster_erp/server/routes/email.py:122 |
POST |
/api/v1/email/send |
send_email |
email.send |
EmailSendRequest |
none | EmailSendResponse |
200 (default) | src/cluster_erp/server/routes/email.py:187 |
Chat endpoints¶
One route that answers a chat message through the intent engine; see Intent assistant.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
POST |
/api/v1/chat/message |
chat_message |
dashboard.read |
ChatRequest |
none | ChatResponse |
200 (default) | src/cluster_erp/server/routes/chat.py:1191 |
Composite party creation endpoints¶
One route that creates a party with its roles in one request, built from PartyCompositeCreate (src/cluster_erp/server/routes/party_composite.py:40-51).
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
POST |
/api/v1/parties/composite |
create_party_composite |
party.create |
PartyCompositeCreate |
none | dict |
201 |
src/cluster_erp/server/routes/party_composite.py:54 |
Party roles endpoints¶
Three routes that turn on the customer, supplier, or employee role of an existing party.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
POST |
/api/v1/parties/{party_id}/roles/customer |
enable_customer_role |
customer.create |
dict[str, Any] |
none | dict |
201 |
src/cluster_erp/server/routes/party_roles.py:58 |
POST |
/api/v1/parties/{party_id}/roles/supplier |
enable_supplier_role |
supplier.create |
dict[str, Any] |
none | dict |
201 |
src/cluster_erp/server/routes/party_roles.py:80 |
POST |
/api/v1/parties/{party_id}/roles/employee |
enable_employee_role |
employee.create |
dict[str, Any] |
none | dict |
201 |
src/cluster_erp/server/routes/party_roles.py:102 |
Tenant fields endpoints¶
Two routers: router under /api/v1/{module}/_fields for field definitions, field settings, and the field catalogue, and overlay_router for /api/v1/_overlay. The module path segment is checked against the declared specs (src/cluster_erp/server/routes/tenant_fields.py:1-9); see Tenant fields.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
GET |
/api/v1/{module}/_fields/definitions/ |
list_definitions |
tenant_field_definition.read |
none | module, entity_type |
list[FieldDefinitionRead] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:150 |
POST |
/api/v1/{module}/_fields/definitions/ |
create_definition |
tenant_field_definition.create |
FieldDefinitionCreate |
module |
FieldDefinitionRead |
201 |
src/cluster_erp/server/routes/tenant_fields.py:167 |
GET |
/api/v1/{module}/_fields/definitions/{definition_id} |
get_definition |
tenant_field_definition.read |
none | module |
FieldDefinitionRead |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:181 |
PATCH |
/api/v1/{module}/_fields/definitions/{definition_id} |
update_definition |
tenant_field_definition.update |
FieldDefinitionUpdate |
module |
FieldDefinitionRead |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:197 |
POST |
/api/v1/{module}/_fields/definitions/{definition_id}/actions/close |
close_definition |
tenant_field_definition.update |
none | module |
FieldDefinitionRead |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:215 |
POST |
/api/v1/{module}/_fields/definitions/{definition_id}/actions/reopen |
reopen_definition |
tenant_field_definition.update |
none | module |
FieldDefinitionRead |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:232 |
GET |
/api/v1/{module}/_fields/settings/ |
list_settings |
tenant_field_setting.read |
none | module, entity_type |
list[dict[str, Any]] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:252 |
GET |
/api/v1/{module}/_fields/settings/{setting_id} |
get_setting |
tenant_field_setting.read |
none | module |
dict[str, Any] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:273 |
PATCH |
/api/v1/{module}/_fields/settings/{setting_id} |
update_setting |
tenant_field_setting.update |
FieldSettingUpdate |
module |
dict[str, Any] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:294 |
GET |
/api/v1/{module}/_fields/catalog/ |
list_catalog |
tenant_field_catalog.read |
none | module |
list[dict[str, Any]] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:320 |
POST |
/api/v1/{module}/_fields/catalog/ |
create_catalog_entry |
tenant_field_catalog.create |
FieldCatalogCreate |
module |
dict[str, Any] |
201 |
src/cluster_erp/server/routes/tenant_fields.py:334 |
GET |
/api/v1/{module}/_fields/catalog/{entry_id} |
get_catalog_entry |
tenant_field_catalog.read |
none | module |
dict[str, Any] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:348 |
PATCH |
/api/v1/{module}/_fields/catalog/{entry_id} |
update_catalog_entry |
tenant_field_catalog.update |
FieldCatalogUpdate |
module |
dict[str, Any] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:364 |
POST |
/api/v1/{module}/_fields/catalog/{entry_id}/actions/bind |
bind_catalog_entry |
tenant_field_catalog.update |
FieldCatalogBind |
module |
dict[str, Any] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:379 |
POST |
/api/v1/{module}/_fields/catalog/{entry_id}/actions/derive |
derive_catalog_entry |
tenant_field_catalog.update |
FieldCatalogDerive |
module |
dict[str, Any] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:397 |
POST |
/api/v1/{module}/_fields/catalog/{entry_id}/actions/close |
close_catalog_entry |
tenant_field_catalog.update |
none | module |
dict[str, Any] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:415 |
POST |
/api/v1/{module}/_fields/catalog/{entry_id}/actions/reopen |
reopen_catalog_entry |
tenant_field_catalog.update |
none | module |
dict[str, Any] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:429 |
GET |
/api/v1/_overlay |
get_overlay |
authenticated user (get_current_user) |
none | none | dict[str, Any] |
200 (default) | src/cluster_erp/server/routes/tenant_fields.py:446 |
Error codes¶
The table lists the error codes that the seven route files raise, found by the same syntax-tree scan as on the module pages. Guard, entitlement, and validation errors are listed on Errors.
| Code | HTTP status | Raised in | First site |
|---|---|---|---|
AUTH_PERMISSION_DENIED |
403 |
`` | src/cluster_erp/server/routes/attachments.py:55 |
FILE_NOT_FOUND_ON_DISK |
404 |
`` | src/cluster_erp/server/routes/attachments.py:115 |
HTTP_404 |
404 |
`` | src/cluster_erp/server/routes/party_roles.py:54 |
HTTP_422 |
422 |
`` | src/cluster_erp/server/routes/party_composite.py:37 |
PARTY_ASSIGNMENT_INCOMPLETE |
422 |
`` | src/cluster_erp/server/routes/party_composite.py:134 |
RESOURCE_NOT_FOUND |
404 |
`` | src/cluster_erp/server/routes/attachments.py:112 |
SMTP_ERROR |
502 |
`` | src/cluster_erp/server/routes/email.py:184 |
SMTP_NOT_CONFIGURED |
503 |
`` | src/cluster_erp/server/routes/email.py:132 |
Related pages¶
Verified against commit 92f8051 on 2026-11-13.