Base URL
{{ $baseUrl }}
@php $groups = [ 'System' => [ ['GET', '/api/health', 'API health check', 'Public', 'Returns {"status":"ok"}.'], ['GET', '/api/public/ping', 'Public API health check', 'Public', 'Checks availability of the unauthenticated API surface.'], ], 'Authentication & registration' => [ ['POST', '/api/auth/login', 'Create an API token', 'Public', 'JSON: email, password, optional device_name.'], ['POST', '/api/auth/logout', 'Revoke the current token', 'Bearer', 'Revokes the token used for this request.'], ['POST', '/api/auth/refresh', 'Rotate the current token', 'Bearer', 'Returns a replacement Sanctum bearer token.'], ['GET', '/api/auth/me', 'Get the current account', 'Bearer', 'Returns the authenticated user and resolved organization context.'], ['POST', '/api/auth/forgot-password', 'Request a password reset', 'Public', 'JSON: email. Always returns a safe non-enumerating response.'], ['POST', '/api/auth/reset-password', 'Reset a password', 'Public', 'JSON: email, token, password, password_confirmation.'], ['POST', '/api/auth/reset-password/revoke-sessions', 'Revoke reset-related sessions', 'Public', 'JSON: session_management_token.'], ['POST', '/api/register', 'Start workspace registration', 'Public', 'JSON: name, email, password, terms_accepted. Phone and job title are optional.'], ['GET', '/api/register/{token}', 'Read registration progress', 'Public', 'Returns the current step and safe registration summary.'], ['POST', '/api/register/{token}/verify', 'Verify registration email', 'Public', 'JSON: code (six digits).'], ['POST', '/api/register/{token}/resend', 'Resend verification code', 'Public', 'Rate limited to prevent abuse.'], ['PUT', '/api/register/{token}/organization', 'Save workspace details', 'Public', 'JSON: name, slug, optional phone, job_title, and settings.'], ['POST', '/api/register/{token}/complete', 'Provision the workspace', 'Public', 'Completes registration and returns an authenticated session.'], ], 'Platform administration' => [ ['GET', '/api/admin/organizations', 'List organizations', 'Super admin', 'Paginated platform-wide organization list.'], ['POST', '/api/admin/organizations', 'Create an organization', 'Super admin', 'Creates and provisions a tenant workspace.'], ['GET', '/api/admin/organizations/{organization}/stats', 'Organization statistics', 'Super admin', 'Returns note, project, member, attachment, and storage totals.'], ['POST', '/api/admin/organizations/{organization}/suspend', 'Suspend an organization', 'Super admin', 'Makes tenant mutations read-only.'], ['POST', '/api/admin/organizations/{organization}/activate', 'Activate an organization', 'Super admin', 'Restores normal tenant mutations.'], ], 'Organization' => [ ['POST', '/api/organizations', 'Create my organization', 'Bearer', 'JSON: name and slug. Creates a workspace and makes the current account its Org Admin.'], ['GET', '/api/organization', 'Get organization settings', 'Member', 'Returns branding, settings, and current workspace information.'], ['PUT', '/api/organization', 'Update organization settings', 'Org admin', 'Accepts name, slug, and supported settings fields.'], ['POST', '/api/organization/logo', 'Upload organization logo', 'Org admin', 'Multipart: logo. JPEG, PNG, GIF, or WebP up to 5 MB.'], ], 'Projects' => [ ['GET', '/api/projects', 'List projects', 'Member', 'Paginated tenant-scoped project collection.'], ['POST', '/api/projects', 'Create a project', 'Editor+', 'JSON: name, optional description, key, member_ids.'], ['GET', '/api/projects/{project}', 'Get a project', 'Member', 'Returns project details and related metadata.'], ['PUT', '/api/projects/{project}', 'Update a project', 'Editor+', 'Partial JSON update for name, description, key, members, status, or progress.'], ['DELETE', '/api/projects/{project}', 'Delete a project', 'Editor+', 'Soft-deletes the project according to policy.'], ['POST', '/api/projects/{project}/share', 'Create or refresh a share link', 'Editor+', 'Returns the public project share token and URL.'], ['DELETE', '/api/projects/{project}/share', 'Revoke a share link', 'Editor+', 'Immediately invalidates the active project link.'], ], 'Notes' => [ ['GET', '/api/projects/{project}/notes', 'List project notes', 'Member', 'Supports pagination and server-side note filters.'], ['POST', '/api/projects/{project}/notes', 'Create a note', 'Editor+', 'JSON: title, content, optional type, note_status_id, assignee_ids, label_ids.'], ['POST', '/api/notes/bulk-labels', 'Bulk update note labels', 'Editor+', 'JSON: note_ids, label_ids, operation (add, remove, or replace).'], ['GET', '/api/notes/{note}', 'Get a note', 'Member', 'Returns note, assignments, labels, status, and attachments.'], ['PUT', '/api/notes/{note}', 'Update a note', 'Editor+', 'Partial JSON update of editable note fields.'], ['DELETE', '/api/notes/{note}', 'Delete a note', 'Editor+', 'Soft-deletes the note.'], ['POST', '/api/notes/{note}/status', 'Change note status', 'Editor+', 'JSON: note_status_id. Adds a status-change timeline event.'], ['POST', '/api/notes/{note}/request-update', 'Request an external update', 'Editor+', 'JSON: recipient_email and optional message.'], ['POST', '/api/notes/{note}/reply', 'Post a reply', 'Editor+', 'JSON: content and optional mentioned_user_ids.'], ['GET', '/api/notes/{note}/timeline', 'Get note timeline', 'Member', 'Chronological creation, update, reply, status, label, and attachment events.'], ['GET', '/api/notes/{note}/update-requests', 'List update requests', 'Member', 'Returns active, used, expired, and revoked update links.'], ['DELETE', '/api/notes/{note}/update-requests/{shareToken}', 'Revoke an update request', 'Editor+', 'Invalidates a single external update link.'], ['POST', '/api/notes/{note}/update-requests/{shareToken}/resend', 'Resend an update request', 'Editor+', 'Queues another delivery of the existing request.'], ], 'Attachments' => [ ['POST', '/api/notes/{note}/attachments', 'Upload an attachment', 'Editor+', 'Multipart: file, maximum 50 MB. The response begins with scan_status=pending.'], ['GET', '/api/attachments/{attachment}', 'Get attachment metadata', 'Member', 'Returns scan status, preview kind, size, hashes, and download URL.'], ['GET', '/api/attachments/{attachment}/download', 'Download an attachment', 'Member', 'Returns HTTP 423 until the malware scan is clean.'], ['POST', '/api/attachments/{attachment}/rescan', 'Retry a failed scan', 'Org admin', 'Allowed only when scan_status=error and the quarantined object exists.'], ['DELETE', '/api/attachments/{attachment}', 'Delete an attachment', 'Editor+', 'Deletes both the private object and attachment record.'], ], 'Members' => [ ['GET', '/api/users', 'List organization members', 'Member', 'Tenant-scoped member collection.'], ['POST', '/api/users/invite', 'Add a member', 'Org admin', 'JSON: name, email, role. Existing accounts retain their credentials.'], ['PUT', '/api/users/{user}/role', 'Change membership role', 'Org admin', 'Updates the role only in the selected organization.'], ['PATCH', '/api/users/{user}/access', 'Enable or disable membership', 'Org admin', 'JSON: enabled. Disabled memberships preserve assignments.'], ['DELETE', '/api/users/{user}', 'Remove a membership', 'Org admin', 'Detaches current assignments without deleting the global account.'], ['POST', '/api/users/{user}/resend-invitation', 'Resend an invitation', 'Org admin', 'Queues another invitation email.'], ], 'Statuses & labels' => [ ['GET', '/api/statuses', 'List note statuses', 'Member', 'Ordered tenant status collection.'], ['POST', '/api/statuses', 'Create a status', 'Org admin', 'JSON: label, tone_key, optional sort_order.'], ['PUT', '/api/statuses/{status}', 'Update a status', 'Org admin', 'Partial status update.'], ['DELETE', '/api/statuses/{status}', 'Delete a status', 'Org admin', 'Protected when the status is still in use.'], ['POST', '/api/statuses/reorder', 'Reorder statuses', 'Org admin', 'JSON: ids in the desired order.'], ['GET', '/api/labels', 'List note labels', 'Member', 'Ordered tenant label collection.'], ['POST', '/api/labels', 'Create a label', 'Org admin', 'JSON: name, color (#RRGGBB), optional sort_order.'], ['PUT', '/api/labels/{label}', 'Update a label', 'Org admin', 'Partial label update.'], ['DELETE', '/api/labels/{label}', 'Delete a label', 'Org admin', 'Detaches and deletes the label.'], ['POST', '/api/labels/reorder', 'Reorder labels', 'Org admin', 'JSON: label_ids in the desired order.'], ], 'Requests, activity & notifications' => [ ['GET', '/api/pending-requests', 'List pending public note requests', 'Member', 'Returns unmoderated requests and their scanned images.'], ['POST', '/api/pending-requests/{pendingNoteRequest}/approve', 'Approve a pending request', 'Editor+', 'Creates a normal note from the public submission.'], ['POST', '/api/pending-requests/{pendingNoteRequest}/reject', 'Reject a pending request', 'Editor+', 'Rejects and removes its quarantined attachments.'], ['GET', '/api/activity-logs', 'List activity logs', 'Member', 'Paginated tenant audit trail.'], ['GET', '/api/notifications', 'List current-user notifications', 'Bearer', 'Returns unread and recent notification records.'], ['POST', '/api/notifications/read-all', 'Mark all notifications read', 'Bearer', 'Updates all unread notifications for the current user.'], ['POST', '/api/notifications/{id}/read', 'Mark one notification read', 'Bearer', 'Only affects a notification owned by the current user.'], ], 'Mail & outbound messages' => [ ['GET', '/api/mail-settings', 'Get mail configuration', 'Org admin', 'Returns safe SMTP state and notification preferences; secrets are never returned.'], ['PUT', '/api/mail-settings', 'Update mail configuration', 'Org admin', 'Stores SMTP credentials encrypted.'], ['POST', '/api/mail-settings/test', 'Send a test email', 'Org admin', 'Validates the pending SMTP settings.'], ['POST', '/api/mail-settings/activate', 'Activate organization mail', 'Org admin', 'Enables the tested configuration.'], ['POST', '/api/mail-settings/deactivate', 'Deactivate organization mail', 'Org admin', 'Falls back to platform mail behavior.'], ['GET', '/api/outbound-messages', 'List outbound messages', 'Org admin', 'Paginated encrypted outbox and delivery state.'], ['GET', '/api/outbound-messages/{outboundMailMessage}', 'Get an outbound message', 'Org admin', 'Returns one tenant-scoped message record.'], ['POST', '/api/outbound-messages/{outboundMailMessage}/resend', 'Resend an outbound message', 'Org admin', 'Queues another delivery attempt.'], ], 'Public sharing' => [ ['GET', '/api/public/organizations/{organization}/logo', 'Read public organization logo', 'Public', 'Returns only the public branding asset.'], ['GET', '/api/public/p/{token}', 'Open a shared project', 'Public', 'Returns project branding, global notes, and public-safe timelines.'], ['POST', '/api/public/p/{token}/request-note', 'Request a new note', 'Public', 'Multipart or JSON: name, email, title, details, optional image attachments.'], ['GET', '/api/public/update/{token}', 'Open an update request', 'Public', 'Returns a safe note/request summary and token state.'], ['POST', '/api/public/update/{token}', 'Submit a one-time update', 'Public', 'Multipart: name, email, message, optional six-digit code and attachments/files.'], ], ]; $endpointCount = collect($groups)->sum(fn ($items) => count($items)); $baseUrl = rtrim(url('/api'), '/'); @endphp
REST API reference
A tenant-safe Laravel API for projects, notes, public collaboration, private attachments, update requests, mail delivery, and auditable workspace administration.
Quick start
All authenticated endpoints live under /api. Send JSON with an Accept: application/json header and use the token returned by login.
{{ $baseUrl }}
application/json, except multipart uploads.
GET /api/health requires no token.
curl -X POST '{{ $baseUrl }}/auth/login' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"email": "alice@example.com",
"password": "your-password",
"device_name": "integration"
}'Security
The login endpoint returns a Sanctum token. Store it securely and attach it to subsequent requests. Logout revokes only the current token; refresh rotates it.
curl '{{ $baseUrl }}/projects' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN'Isolation
The organization is resolved from the authenticated account. Cross-tenant model identifiers return 404.
Platform routes use /api/admin. A selected tenant context may be supplied with X-Organization-ID where supported.
super_admin, org_admin, editor, and viewer. Suspended tenants remain readable but cannot mutate data.
Response contract
| Status | Meaning | Typical shape |
|---|---|---|
200 / 201 | Successful read or creation | Resource key or paginated data |
401 | Missing or invalid token | {"message":"Unauthenticated."} |
403 | Role/policy denial or suspended mutation | {"message":"…"} |
404 | Missing or cross-tenant resource | {"message":"Not Found"} |
409 / 410 | Used, revoked, or expired one-time flow | {"message":"…"} |
422 | Validation failure | {"message":"…","errors":{…}} |
423 | Attachment has not passed scanning | {"message":"…"} |
429 | Rate limit exceeded | Standard Laravel throttle response |
Private files
Uploads enter private quarantine with scan_status=pending. A worker streams them to ClamAV. Clean files become previewable; infected files are deleted; scanner errors remain fail-closed and can be retried by an organization administrator.
curl -X POST '{{ $baseUrl }}/notes/42/attachments' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-F 'file=@./screenshot.png'Complete catalog
Search by method, path, capability, or access level. Path parameters use braces; list endpoints return Laravel pagination metadata where applicable.