Download OpenAPI specification:Download
Tourfold is a comprehensive SaaS platform for field service management. Our API provides programmatic access to manage jobs, tours, users and much more.
Use the endpoints documented here to automate dispatching flows, synchronize your account data, and build custom integrations for your operators and mobile clients.
Request and response examples follow Alpine Facility Services GmbH, a fictional Vienna maintenance company. The example identities are illustrative and are not created automatically in customer workspaces.
For detailed documentation, workflow guides, and onboarding support, visit https://docs.tourfold.com.
Returns the tenant billing profile used for invoices and Stripe customer metadata.
AlpineBillingProfile
{- "billing_full_name": "Mara Berger",
- "billing_business_name": "Alpine Facility Services GmbH",
- "billing_vat_number": "ATU12345678",
- "billing_country_code": "AT",
- "billing_email": "billing@example.invalid",
- "billing_address_line1": "Riverside Office 17",
- "billing_city": "Vienna",
- "billing_postal_code": "1210",
- "billing_state_province": "Vienna",
- "lock_version": 0
}JSON Merge Patch (RFC 7386): omitted fields remain unchanged; a field set to null is cleared. Fields required for invoicing (billing_email, billing_address_line1, billing_city, billing_postal_code, billing_country_code, and a full name or business name) cannot be cleared — explicit null on those is rejected with 422. Updates the tenant billing profile and syncs supported fields to Stripe when the tenant has a Stripe customer.
| billing_full_name | string or null Billing contact full name. Omitted leaves the value unchanged; explicit null clears it, but a business name must then be present (a full name or business name is required for invoicing). |
| billing_business_name | string or null Billing business name. Omitted leaves the value unchanged; explicit null clears it, but a full name must then be present (a full name or business name is required for invoicing). |
| billing_vat_number | string or null VAT number. Read-only after signup — contact support to change. Omitted leaves the value unchanged; explicit null clears it. |
| billing_country_code | string or null ISO 3166-1 alpha-2 billing country code. Read-only after signup — contact support to change. Required for invoicing: omitted leaves the value unchanged; explicit null is rejected with 422. |
| billing_email | string or null Email address that receives PDF invoices. Required for invoicing: omitted leaves the value unchanged; explicit null is rejected with 422. |
| billing_address_line1 | string or null Street address, first line. Required for invoicing: omitted leaves the value unchanged; explicit null is rejected with 422. |
| billing_address_line2 | string or null Street address, second line. Omitted leaves the value unchanged; explicit null clears it. |
| billing_city | string or null City. Required for invoicing: omitted leaves the value unchanged; explicit null is rejected with 422. |
| billing_postal_code | string or null Postal code. Required for invoicing: omitted leaves the value unchanged; explicit null is rejected with 422. |
| billing_state_province | string or null State / province / region. Omitted leaves the value unchanged; explicit null clears it. |
| lock_version | integer or null <int64> Optimistic-locking version: validated when provided (409 on mismatch) if a profile already exists; omitting it skips the concurrency check. Ignored when creating the first profile. |
UpdateBillingProfileNull
{- "billing_address_line2": null,
- "billing_city": "Vienna",
- "lock_version": 0
}UpdatedAlpineBillingProfile
{- "billing_full_name": "Mara Berger",
- "billing_business_name": "Alpine Facility Services GmbH",
- "billing_vat_number": "ATU12345678",
- "billing_country_code": "AT",
- "billing_email": "billing@example.invalid",
- "billing_address_line1": "Riverside Office 17",
- "billing_city": "Vienna",
- "billing_postal_code": "1210",
- "billing_state_province": "Vienna",
- "lock_version": 0
}Returns a paginated list of tags. Available to all authenticated users.
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
AlpineTagsPage
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20",
- "created_at": "2026-08-20T08:15:00Z",
- "updated_at": "2026-08-20T08:15:00Z",
- "lock_version": 0,
- "usage_count": 1
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Creates a new tag. Requires 'tags:update' grant.
| name required | string non-empty Tag name |
| color required | string non-empty Tag color (hex or CSS color value) |
CreateUrgentTag
{- "name": "urgent",
- "color": "#D92D20"
}CreatedUrgentTag
{- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20",
- "created_at": "2026-08-20T08:15:00Z",
- "updated_at": "2026-08-20T08:15:00Z",
- "lock_version": 0,
- "usage_count": 1
}Returns a single tag by its ID. Available to all authenticated users.
| tag_id required | string <uuid> UUID of the tag. |
UrgentTag
{- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20",
- "created_at": "2026-08-20T08:15:00Z",
- "updated_at": "2026-08-20T08:15:00Z",
- "lock_version": 0,
- "usage_count": 1
}Deletes a tag by ID. Requires 'tags:update' grant.
| tag_id required | string <uuid> UUID of the tag. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Partial update: omitted fields remain unchanged. Requires 'tags:update' grant.
| tag_id required | string <uuid> UUID of the tag. |
| name | string Tag name. Omit to leave the value unchanged. Must not be null or blank. |
| color | string Tag color (hex or CSS color value). Omit to leave the value unchanged. Must not be null or blank. |
| lock_version | integer or null <int64> Optimistic lock version. If provided, the update will fail with 409 if the stored version does not match. |
UpdateUrgentTagColor
{- "color": "#B42318",
- "lock_version": 0
}UpdatedUrgentTag
{- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#B42318",
- "created_at": "2026-08-20T08:15:00Z",
- "updated_at": "2026-08-20T09:15:00Z",
- "lock_version": 1,
- "usage_count": 1
}Replaces the tags assigned to a user. Empty tag_ids removes all assigned tags.
| user_id required | string <uuid> UUID of the user. |
| tag_ids required | Array of strings <uuid> unique [ items <uuid > ] Tag IDs to assign to the user. Empty array removes all assigned tags. |
| lock_version | integer or null <int64> Optimistic locking version of the user aggregate; validated when provided (409 on mismatch), omitting it skips the concurrency check |
ReplaceWithUrgentTag
{- "tag_ids": [
- "00000000-0000-4000-8000-000000005001"
], - "lock_version": 0
}JonasWithReplacedTags
{- "id": "00000000-0000-4000-8000-000000001002",
- "email": "jonas.leitner@example.invalid",
- "phone_number": "+436641234567",
- "roles": [
- "technician"
], - "skills": [
- {
- "id": "00000000-0000-4000-8000-000000006101",
- "name": "HVAC maintenance",
- "skill": "00000000-0000-4000-8000-000000006001",
- "skill_type": "skill",
- "short_key": "hvac-maintenance"
}
], - "firstname": "Jonas",
- "lastname": "Leitner",
- "created_at": "2026-08-20T08:05:00Z",
- "updated_at": "2026-08-20T08:05:00Z",
- "status": "ACTIVE",
- "lock_version": 0,
- "can_resend_set_password_email": false,
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Returns the skills assigned to a user.
| user_id required | string <uuid> Example: 1ec2dffe-2a5b-4c59-9ea2-9f0c3c5ab5af UUID of the user whose skills should be retrieved |
JonasSkills
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000006101",
- "name": "HVAC maintenance",
- "skill": "00000000-0000-4000-8000-000000006001",
- "skill_type": "skill",
- "short_key": "hvac-maintenance"
}
]
}Replaces the skills assigned to a user. Empty skill_ids removes all assigned skills.
| user_id required | string <uuid> UUID of the user. |
| skill_ids required | Array of strings <uuid> unique [ items <uuid > ] Skill IDs to assign to the user. Empty array removes all assigned skills. |
| lock_version | integer or null <int64> Optimistic locking version of the user aggregate; validated when provided (409 on mismatch), omitting it skips the concurrency check |
ReplaceWithHvacSkill
{- "skill_ids": [
- "00000000-0000-4000-8000-000000006001"
], - "lock_version": 0
}JonasWithReplacedSkills
{- "id": "00000000-0000-4000-8000-000000001002",
- "email": "jonas.leitner@example.invalid",
- "phone_number": "+436641234567",
- "roles": [
- "technician"
], - "skills": [
- {
- "id": "00000000-0000-4000-8000-000000006101",
- "name": "HVAC maintenance",
- "skill": "00000000-0000-4000-8000-000000006001",
- "skill_type": "skill",
- "short_key": "hvac-maintenance"
}
], - "firstname": "Jonas",
- "lastname": "Leitner",
- "created_at": "2026-08-20T08:05:00Z",
- "updated_at": "2026-08-20T08:05:00Z",
- "status": "ACTIVE",
- "lock_version": 0,
- "can_resend_set_password_email": false,
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Returns a paginated list of users in your account. Service accounts and API-only users are excluded.
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
| sort | Array of strings Example: sort=last_name:asc Repeated sorting criteria in |
| search | string Search term for email, first name, or last name. |
| role | string Example: role=driver Filter by role name. Matching is case-insensitive. |
| status | string Default: "ACTIVE" Enum: "ACTIVE" "BLOCKED" "INACTIVE" "ALL" Filter by user status (ACTIVE, BLOCKED, INACTIVE, ALL). Default is ACTIVE. |
| role_ids | Array of strings <uuid> [ items <uuid > ] Filter users by one or more role UUIDs. Only users assigned to at least one of the specified roles are returned. |
| skill_ids | Array of strings <uuid> [ items <uuid > ] Filter users by one or more skill UUIDs. Only users with at least one of the specified skill offerings are returned. |
| tag_names | Array of strings Filter users by tag name (OR semantics: returns users that have at least one of the given tags). Multiple values are supported. When omitted, no tag filtering is applied. |
| updated_from | string <date-time> Example: updated_from=2024-01-01T00:00:00Z Lower bound for |
| updated_to | string <date-time> Example: updated_to=2024-12-31T23:59:59Z Upper bound for |
UsersResponse
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000001001",
- "email": "mara.berger@example.invalid",
- "phone_number": "+436601234567",
- "roles": [
- "dispatcher"
], - "skills": [ ],
- "firstname": "Mara",
- "lastname": "Berger",
- "created_at": "2026-08-20T08:00:00Z",
- "updated_at": "2026-08-20T08:00:00Z",
- "status": "ACTIVE",
- "lock_version": 0,
- "can_resend_set_password_email": false,
- "tags": [ ]
}, - {
- "id": "00000000-0000-4000-8000-000000001002",
- "email": "jonas.leitner@example.invalid",
- "phone_number": "+436641234567",
- "roles": [
- "technician"
], - "skills": [
- {
- "id": "00000000-0000-4000-8000-000000006101",
- "name": "HVAC maintenance",
- "skill": "00000000-0000-4000-8000-000000006001",
- "skill_type": "skill",
- "short_key": "hvac-maintenance"
}
], - "firstname": "Jonas",
- "lastname": "Leitner",
- "created_at": "2026-08-20T08:05:00Z",
- "updated_at": "2026-08-20T08:05:00Z",
- "status": "ACTIVE",
- "lock_version": 0,
- "can_resend_set_password_email": false,
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}
], - "page": {
- "size": 2,
- "total_elements": 2,
- "total_pages": 1,
- "number": 0
}
}Creates a user and assigns the provided roles. Email is immutable after creation.
| Origin | string |
| email required | string <email> non-empty Email address of the user |
| firstname required | string non-empty First name of the user |
| lastname required | string non-empty Last name of the user |
| phone_number | string International phone number. An explicit '+' country code is required; common formatting is accepted and normalized to canonical E.164. National numbers are rejected. Omit the field to leave it unset; a blank value is rejected. |
| role_ids required | Array of strings <uuid> non-empty unique [ items <uuid > ] Roles to assign to the user |
| skill_ids | Array of strings <uuid> unique [ items <uuid > ] Skills to assign to the user |
| tag_ids | Array of strings <uuid> unique [ items <uuid > ] Tags to assign to the user. When omitted, no tags are assigned. |
CreateAlpineTechnician
{- "email": "jonas.leitner@example.invalid",
- "firstname": "Jonas",
- "lastname": "Leitner",
- "phone_number": "+43 664 123 45 67",
- "role_ids": [
- "00000000-0000-4000-8000-000000001101"
], - "skill_ids": [
- "00000000-0000-4000-8000-000000006001"
], - "tag_ids": [
- "00000000-0000-4000-8000-000000005001"
]
}CreateUserResponse
{- "id": "00000000-0000-4000-8000-000000001002",
- "email": "jonas.leitner@example.invalid",
- "phone_number": "+436641234567",
- "roles": [
- "technician"
], - "skills": [
- {
- "id": "00000000-0000-4000-8000-000000006101",
- "name": "HVAC maintenance",
- "skill": "00000000-0000-4000-8000-000000006001",
- "skill_type": "skill",
- "short_key": "hvac-maintenance"
}
], - "firstname": "Jonas",
- "lastname": "Leitner",
- "created_at": "2026-08-20T08:05:00Z",
- "updated_at": "2026-08-20T08:05:00Z",
- "status": "ACTIVE",
- "lock_version": 0,
- "can_resend_set_password_email": false,
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Unblocks a user who was blocked due to failed login attempts.
| user_id required | string <uuid> Example: 1ec2dffe-2a5b-4c59-9ea2-9f0c3c5ab5af UUID of the user to unblock |
| Origin | string |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Resends the email that lets an invited user set their password.
| user_id required | string <uuid> Example: 1ec2dffe-2a5b-4c59-9ea2-9f0c3c5ab5af UUID of the user to receive the set-password email |
| Origin | string |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Transfers the owner role to the target user. Only the current owner may call this endpoint. The current owner loses owner and keeps admin.
| user_id required | string <uuid> UUID of the user. |
TransferredOwner
{- "id": "00000000-0000-4000-8000-000000001002",
- "email": "jonas.leitner@example.invalid",
- "phone_number": "+436641234567",
- "roles": [
- "technician"
], - "skills": [
- {
- "id": "00000000-0000-4000-8000-000000006101",
- "name": "HVAC maintenance",
- "skill": "00000000-0000-4000-8000-000000006001",
- "skill_type": "skill",
- "short_key": "hvac-maintenance"
}
], - "firstname": "Jonas",
- "lastname": "Leitner",
- "created_at": "2026-08-20T08:05:00Z",
- "updated_at": "2026-08-20T08:05:00Z",
- "status": "ACTIVE",
- "lock_version": 0,
- "can_resend_set_password_email": false,
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Deactivates the user, preventing them from accessing the system.
| user_id required | string <uuid> Example: 1ec2dffe-2a5b-4c59-9ea2-9f0c3c5ab5af UUID of the user to deactivate |
DeactivatedUser
{- "id": "00000000-0000-4000-8000-000000001002",
- "email": "jonas.leitner@example.invalid",
- "phone_number": "+436641234567",
- "roles": [
- "technician"
], - "skills": [ ],
- "firstname": "Jonas",
- "lastname": "Leitner",
- "created_at": "2026-08-20T08:05:00Z",
- "updated_at": "2026-08-20T10:00:00Z",
- "status": "INACTIVE",
- "lock_version": 1,
- "can_resend_set_password_email": false,
- "tags": [ ]
}Activates the user, allowing them to access the system.
| user_id required | string <uuid> Example: 1ec2dffe-2a5b-4c59-9ea2-9f0c3c5ab5af UUID of the user to activate |
ActivatedUser
{- "id": "00000000-0000-4000-8000-000000001002",
- "email": "jonas.leitner@example.invalid",
- "phone_number": "+436641234567",
- "roles": [
- "technician"
], - "skills": [
- {
- "id": "00000000-0000-4000-8000-000000006101",
- "name": "HVAC maintenance",
- "skill": "00000000-0000-4000-8000-000000006001",
- "skill_type": "skill",
- "short_key": "hvac-maintenance"
}
], - "firstname": "Jonas",
- "lastname": "Leitner",
- "created_at": "2026-08-20T08:05:00Z",
- "updated_at": "2026-08-20T08:05:00Z",
- "status": "ACTIVE",
- "lock_version": 0,
- "can_resend_set_password_email": false,
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Allows an authenticated user to change their own password by providing the current password. No email roundtrip is required. The new password must satisfy the password policy (minimum 8 characters).
| current_password required | string non-empty The user's current password. Used to authorize the password change. |
| new_password required | string [ 8 .. 2147483647 ] characters The desired new password. Must satisfy the password policy (minimum 8 characters). |
ChangeOwnPassword
{- "current_password": "current-password-example",
- "new_password": "new-password-example"
}{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Returns a single user by their unique identifier.
| user_id required | string <uuid> Example: 1ec2dffe-2a5b-4c59-9ea2-9f0c3c5ab5af UUID of the user to retrieve |
UserResponse
{- "id": "00000000-0000-4000-8000-000000001002",
- "email": "jonas.leitner@example.invalid",
- "phone_number": "+436641234567",
- "roles": [
- "technician"
], - "skills": [
- {
- "id": "00000000-0000-4000-8000-000000006101",
- "name": "HVAC maintenance",
- "skill": "00000000-0000-4000-8000-000000006001",
- "skill_type": "skill",
- "short_key": "hvac-maintenance"
}
], - "firstname": "Jonas",
- "lastname": "Leitner",
- "created_at": "2026-08-20T08:05:00Z",
- "updated_at": "2026-08-20T08:05:00Z",
- "status": "ACTIVE",
- "lock_version": 0,
- "can_resend_set_password_email": false,
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Soft-deletes a user by marking the record as deleted (sets deleted_at timestamp). When anonymize=true, also anonymizes personal data (email, firstname, lastname, phone). The user will no longer appear in any API responses. Users cannot delete themselves. Users with the owner role cannot be deleted.
| user_id required | string <uuid> Example: 1ec2dffe-2a5b-4c59-9ea2-9f0c3c5ab5af UUID of the user to delete |
| anonymize | boolean Example: anonymize=true When true, anonymizes personal data (email, firstname, lastname, phone) in addition to soft-deleting |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}JSON Merge Patch (RFC 7386) update of a user. Fields omitted remain unchanged, fields set to null are cleared. Email cannot be changed.
| user_id required | string <uuid> UUID of the user. |
| firstname | string First name of the user. Omitted leaves the value unchanged. Required: it cannot be cleared, and null or a blank value is rejected. |
| lastname | string Last name of the user. Omitted leaves the value unchanged. Required: it cannot be cleared, and null or a blank value is rejected. |
| phone_number | string or null International phone number. An explicit '+' country code is required; common formatting is accepted and normalized to canonical E.164. National numbers are rejected. Omitted leaves the value unchanged; explicit null clears it; a blank value is rejected. |
| role_ids | Array of strings <uuid> unique [ items <uuid > ] Roles to assign to the user. Omitted leaves the assignment unchanged; when provided it replaces the assigned roles and must contain at least one role. Explicit null and empty arrays are rejected (422). |
| lock_version | integer or null <int64> Optimistic locking version of the user aggregate; validated when provided (409 on mismatch), omitting it skips the concurrency check |
UpdateUserNull
{- "lock_version": 2,
- "firstname": "Mara",
- "phone_number": null
}UpdateUserResponse
{- "id": "00000000-0000-4000-8000-000000001002",
- "email": "jonas.leitner@example.invalid",
- "phone_number": "+436641234567",
- "roles": [
- "technician"
], - "skills": [
- {
- "id": "00000000-0000-4000-8000-000000006101",
- "name": "HVAC maintenance",
- "skill": "00000000-0000-4000-8000-000000006001",
- "skill_type": "skill",
- "short_key": "hvac-maintenance"
}
], - "firstname": "Jonas",
- "lastname": "Leitner",
- "created_at": "2026-08-20T08:05:00Z",
- "updated_at": "2026-08-20T08:05:00Z",
- "status": "ACTIVE",
- "lock_version": 0,
- "can_resend_set_password_email": false,
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}CurrentUserResponse
{- "id": "00000000-0000-4000-8000-000000001002",
- "email": "jonas.leitner@example.invalid",
- "phone_number": "+436641234567",
- "roles": [
- "technician"
], - "skills": [
- {
- "id": "00000000-0000-4000-8000-000000006101",
- "name": "HVAC maintenance",
- "skill": "00000000-0000-4000-8000-000000006001",
- "skill_type": "skill",
- "short_key": "hvac-maintenance"
}
], - "firstname": "Jonas",
- "lastname": "Leitner",
- "created_at": "2026-08-20T08:05:00Z",
- "updated_at": "2026-08-20T08:05:00Z",
- "status": "ACTIVE",
- "lock_version": 0,
- "can_resend_set_password_email": false,
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Returns a paginated list of skills.
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
| sort | Array of strings Example: sort=name:asc Repeated sorting criteria in |
| search | string Search term for skill, skill type, short_key, or name. |
| updated_from | string <date-time> Lower bound for |
| updated_to | string <date-time> Upper bound for |
SkillsResponse
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000006001",
- "created_at": "2026-08-20T08:12:00Z",
- "updated_at": "2026-08-20T08:12:00Z",
- "skill": "HVAC_MAINTENANCE",
- "skill_type": "MAINTENANCE",
- "name": "HVAC maintenance",
- "short_key": "HVAC",
- "lock_version": 0
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Creates a new skill with the provided information
| skill required | string [ 0 .. 32 ] characters Skill identifier |
| skill_type required | string [ 0 .. 32 ] characters Skill type |
| name required | string [ 0 .. 255 ] characters Skill name |
| short_key required | string [ 0 .. 10 ] characters Short key identifier |
CreateHvacMaintenanceSkill
{- "skill": "HVAC_MAINTENANCE",
- "skill_type": "MAINTENANCE",
- "name": "HVAC maintenance",
- "short_key": "HVAC"
}SkillResponse
{- "id": "00000000-0000-4000-8000-000000006001",
- "skill": "HVAC_MAINTENANCE",
- "skill_type": "MAINTENANCE",
- "name": "HVAC maintenance",
- "short_key": "HVAC",
- "created_at": "2026-08-20T08:12:00Z",
- "updated_at": "2026-08-20T08:12:00Z",
- "lock_version": 0
}Retrieves a specific skill by its ID
| skill_id required | string <uuid> UUID of the skill. |
SkillsResponse
{- "id": "00000000-0000-4000-8000-000000006001",
- "created_at": "2026-08-20T08:12:00Z",
- "updated_at": "2026-08-20T08:12:00Z",
- "skill": "HVAC_MAINTENANCE",
- "skill_type": "MAINTENANCE",
- "name": "HVAC maintenance",
- "short_key": "HVAC",
- "lock_version": 0
}Deletes a skill by its ID
| skill_id required | string <uuid> UUID of the skill. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Partial update: omitted fields remain unchanged (JSON Merge Patch, RFC 7386).
| skill_id required | string <uuid> UUID of the skill. |
| skill | string Skill identifier (max 32 characters). Omitted leaves the value unchanged; explicit null is rejected (422) — it is required and cannot be cleared. |
| skill_type | string Skill type (max 32 characters). Omitted leaves the value unchanged; explicit null is rejected (422) — it is required and cannot be cleared. |
| name | string Skill name (max 255 characters). Omitted leaves the value unchanged; explicit null is rejected (422) — it is required and cannot be cleared. |
| short_key | string Short key identifier (max 10 characters). Omitted leaves the value unchanged; explicit null is rejected (422) — it is required and cannot be cleared. |
| lock_version | integer or null <int64> Optimistic-locking version of the skill: validated when provided (409 on mismatch); omitting it skips the concurrency check |
UpdateSkillName
{- "lock_version": 2,
- "name": "Advanced HVAC maintenance"
}UpdateSkillResponse
{- "id": "00000000-0000-4000-8000-000000006001",
- "skill": "HVAC_MAINTENANCE",
- "skill_type": "MAINTENANCE",
- "name": "HVAC maintenance",
- "short_key": "HVAC",
- "created_at": "2026-08-20T08:12:00Z",
- "updated_at": "2026-08-20T08:12:00Z",
- "lock_version": 0
}Returns invoice summaries for Stripe-backed self-service tenants. Other plan kinds return an empty list. Stripe is the source of truth: the service fetches a bounded window of the most recent 100 invoices from Stripe and page/size paginate over that fetched window (newest first). page.total_elements therefore never exceeds 100 even if Stripe holds more history.
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
AlpineInvoicesPage
{- "items": [
- {
- "id": "in_alpine_2026_08",
- "number": "AFS-2026-08",
- "status": "paid",
- "currency": "eur",
- "amount_due": 12900,
- "amount_paid": 12900,
- "amount_remaining": 0,
- "created_at": "2026-08-01T08:00:00Z",
- "period_start": "2026-08-01T00:00:00Z",
- "period_end": "2026-09-01T00:00:00Z"
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Returns the Stripe invoice PDF URL after verifying the invoice belongs to this tenant's Stripe customer.
| invoice_id required | string Identifier of the invoice. |
AlpineInvoiceDownload
Query SMS message history for reporting and auditing. Returns all SMS sent through the system with status, timestamps, and gateway information.
Returns a paginated list of SMS messages for the current tenant, with optional filtering by date range and status.
**Date Range:**
- Defaults to last 28 days if not specified
- Filters on the `scheduled_at` timestamp using a half-open range
- Use RFC 3339 format (e.g., 2024-01-15T10:30:00Z)
**Status Values:**
- SCHEDULED: Waiting to be sent
- SENDING: Currently being sent
- SENT: Successfully accepted by gateway
- DELIVERED: Confirmed delivered to recipient (Twilio only, via webhook)
- FAILED: Failed to send
**Sorting:**
- Default: `scheduled_at:desc` (newest first)
- Allowed fields: scheduled_at, sent_at, status, created_at, to_number, gateway_name
- Format: `field:asc` or `field:desc`
- Multiple sort criteria supported
| scheduled_from | string <date-time> Example: scheduled_from=2024-01-01T00:00:00Z Lower bound for |
| scheduled_to | string <date-time> Example: scheduled_to=2024-12-31T23:59:59Z Upper bound for |
| status | string Enum: "SCHEDULED" "SENDING" "SENT" "DELIVERED" "FAILED" Example: status=SENT Filter by SMS status |
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 1000 ] Default: 100 Example: size=100 Number of items per page (max 1000). The cap is deliberately higher than the platform default of 100 because this is a report/export-style endpoint. |
| sort | Array of strings Example: sort=scheduled_at:desc Repeated sorting criteria in |
SmsReportExample
{- "items": [
- {
- "id": "123e4567-e89b-12d3-a456-426614174001",
- "tenant_id": "123e4567-e89b-12d3-a456-426614174000",
- "to_number": "+12025551234",
- "from_number": "+12025559999",
- "message": "Your appointment is confirmed for tomorrow at 10 AM.",
- "gateway_name": "Primary Twilio",
- "scheduled_at": "2024-01-15T10:30:00Z",
- "sent_at": "2024-01-15T10:30:05Z",
- "status": "DELIVERED",
- "created_at": "2024-01-15T10:29:55Z"
}, - {
- "id": "123e4567-e89b-12d3-a456-426614174002",
- "tenant_id": "123e4567-e89b-12d3-a456-426614174000",
- "to_number": "+12025555678",
- "from_number": "+12025559999",
- "message": "Test SMS from Tourfold.",
- "gateway_name": "Fallback Custom",
- "scheduled_at": "2024-01-15T09:15:00Z",
- "sent_at": "2024-01-15T09:15:02Z",
- "status": "SENT",
- "created_at": "2024-01-15T09:14:50Z"
}, - {
- "id": "123e4567-e89b-12d3-a456-426614174003",
- "tenant_id": "123e4567-e89b-12d3-a456-426614174000",
- "to_number": "+12025559876",
- "message": "Reminder: Your case is scheduled for review.",
- "gateway_name": "Primary Twilio",
- "scheduled_at": "2024-01-15T08:00:00Z",
- "status": "FAILED",
- "failure_reason": "Authentication error: Invalid credentials",
- "created_at": "2024-01-15T07:59:55Z"
}
], - "page": {
- "number": 0,
- "size": 100,
- "total_elements": 3,
- "total_pages": 1
}
}Retrieves a paginated list of all relations in the tenant
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
RelationsPage
{- "items": [
- {
- "id": "6f3d2a10-0000-4000-8000-000000000301",
- "a": {
- "definition_slug": "equipment",
- "cardinality": "ONE",
- "required": false,
- "slug": "maintenance_requests",
- "title": "Maintenance Requests",
- "is_hidden": false,
- "translations": {
- "en": {
- "singular": "Maintenance Request",
- "plural": "Maintenance Requests"
}, - "de": {
- "singular": "Wartungsanfrage",
- "plural": "Wartungsanfragen"
}
}
}, - "b": {
- "definition_slug": "maintenance_request",
- "cardinality": "MANY",
- "required": true,
- "slug": "equipment",
- "title": "Equipment",
- "is_hidden": false,
- "translations": {
- "en": {
- "singular": "Equipment",
- "plural": "Equipment"
}, - "de": {
- "singular": "Anlage",
- "plural": "Anlagen"
}
}
}, - "read_only": false
}
], - "page": {
- "size": 1,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
} Creates one or more relations between custom object definitions. Each relation has two
positional sides (`a` and `b`) — there is no inherent direction; both are stored
symmetrically. Each side independently declares its own cardinality, required flag,
navigation slug, and title.
### Cardinality convention
`sideX.cardinality` describes **how many instances of X appear per joined instance of Y**
(standard ERD multiplicity drawn at this side of the diamond).
- `sideA = ONE, sideB = MANY` → one A has many B's; each B has one A (1:N).
- `sideA = ONE, sideB = ONE` → 1:1.
- `sideA = MANY, sideB = MANY` → many-to-many.
To allow "one Person writes many Books", set `book.cardinality = MANY`
('many books per person') and `person.cardinality = ONE` ('one person per book').
To rejection-test this: providing multiple targets when the target side is `ONE`
returns HTTP 422 `errorType=cardinality-violation-source`.
### Required convention
Set `required=true` on the side whose **instances cannot be created without this
relation**. Enforced at instance creation by `validateRequiredRelations` against the
side that matches the definition being created. Missing-relation rejection surfaces as
HTTP 422 `errorType=required-relation`.
### Example 1 — Person ↔ Book (1:N, Book requires an Author)
One Person can write many Books, and a Book cannot exist without an Author.
```
POST /api/v2/custom-objects/relations
{
"relations": [{
"a": {
"definition_slug": "person",
"cardinality": "ONE",
"required": false,
"slug": "books",
"title": "Books",
"is_hidden": false,
"translations": {"en": {"singular": "Book", "plural": "Books"}}
},
"b": {
"definition_slug": "book",
"cardinality": "MANY",
"required": true,
"slug": "author",
"title": "Author",
"is_hidden": false,
"translations": {"en": {"singular": "Author", "plural": "Authors"}}
}
}]
}
```
- `b.cardinality = MANY` ⇒ each Person has many Books.
- `a.cardinality = ONE` ⇒ each Book has one Person.
- `b.required = true` ⇒ creating a Book without `author` returns 422 `required-relation`.
- `a.required = false` ⇒ a Person with zero Books is valid.
The working integration analogue is `HumanCarRelationIntegrationTest`
(`should enforce required relation on creation`, `should enforce required many relation
as at least one association`).
### Example 2 — Tracker ↔ Location (1:1, Tracker requires Location)
A tracker (e.g. a GPS device) needs a location to be useful. The location side carries
`settings_type: "location"` which activates the additional 1:1 + location
constraints from `LocationRelationSettingsValidator`.
**Convention:** `location` is a built-in type — customers only ever declare it
as an attribute on another definition, never edit it directly. So put the consuming
custom object (here: `tracker`) on side `a` and `location` on side `b`.
```
POST /api/v2/custom-objects/relations
{
"relations": [{
"a": {
"definition_slug": "tracker",
"cardinality": "ONE",
"required": true,
"slug": "location",
"title": "Location",
"is_hidden": false,
"translations": {"en": {"singular": "Location", "plural": "Locations"}}
},
"b": {
"definition_slug": "location",
"cardinality": "ONE",
"required": false,
"slug": "tracker",
"title": "Tracker",
"is_hidden": false,
"translations": {"en": {"singular": "Tracker", "plural": "Trackers"}}
},
"settings": { "settings_type": "location", "icon_file_id": null }
}]
}
```
- Both sides `cardinality = ONE` ⇒ 1:1 (each tracker has one location, each location belongs to one tracker).
- `a.required = true` on the tracker side ⇒ creating a tracker without `location` returns 422 `required-relation`.
- `b.required = false` on the location side ⇒ a location can exist with no tracker pointing at it.
- `settings.settings_type = "location"` ⇒ also rejects non-1:1 configurations (422
`errorType=location-relation-must-be-one-to-one`) and rejects relations where neither
side is `location` (422 `errorType=location-relation-must-target-property-location`).
### Validation summary
- Missing required relation at instance creation → 422 `required-relation`.
- Too many targets for a `ONE`-target relation → 422 `cardinality-violation-source`.
- Target already linked to another source when source side is `ONE` → 422 `cardinality-violation-target`.
- Location-specific shape errors → 400 with `location-relation-*` error types
(see `LocationRelationCardinalityApiTest`).
required | Array of objects (RelationSchema) List of relations to create | ||||||
Array
| |||||||
CreateMaintenanceEquipmentRelation
{- "relations": [
- {
- "a": {
- "definition_slug": "equipment",
- "cardinality": "ONE",
- "required": false,
- "slug": "maintenance_requests",
- "title": "Maintenance Requests",
- "is_hidden": false,
- "translations": {
- "en": {
- "singular": "Maintenance Request",
- "plural": "Maintenance Requests"
}, - "de": {
- "singular": "Wartungsanfrage",
- "plural": "Wartungsanfragen"
}
}
}, - "b": {
- "definition_slug": "maintenance_request",
- "cardinality": "MANY",
- "required": true,
- "slug": "equipment",
- "title": "Equipment",
- "is_hidden": false,
- "translations": {
- "en": {
- "singular": "Equipment",
- "plural": "Equipment"
}, - "de": {
- "singular": "Anlage",
- "plural": "Anlagen"
}
}
}
}
]
}CreatedMaintenanceEquipmentRelation
{- "items": [
- {
- "id": "6f3d2a10-0000-4000-8000-000000000301",
- "a": {
- "definition_slug": "equipment",
- "cardinality": "ONE",
- "required": false,
- "slug": "maintenance_requests",
- "title": "Maintenance Requests",
- "is_hidden": false,
- "translations": {
- "en": {
- "singular": "Maintenance Request",
- "plural": "Maintenance Requests"
}, - "de": {
- "singular": "Wartungsanfrage",
- "plural": "Wartungsanfragen"
}
}
}, - "b": {
- "definition_slug": "maintenance_request",
- "cardinality": "MANY",
- "required": true,
- "slug": "equipment",
- "title": "Equipment",
- "is_hidden": false,
- "translations": {
- "en": {
- "singular": "Equipment",
- "plural": "Equipment"
}, - "de": {
- "singular": "Anlage",
- "plural": "Anlagen"
}
}
}, - "read_only": false
}
], - "page": {
- "size": 1,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Associates two instances via the specified relation, providing the side A and side B instance IDs
| relation_id required | string <uuid> UUID of the custom-object relation. |
| side_a_instance_id required | string <uuid> ID of the side A instance |
| side_b_instance_id required | string <uuid> ID of the side B instance |
AssociateRequestWithEquipment
{- "side_a_instance_id": "6f3d2a10-0000-4000-8000-000000000101",
- "side_b_instance_id": "6f3d2a10-0000-4000-8000-000000000201"
}{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Removes the association between two instances for the specified relation
| relation_id required | string <uuid> UUID of the custom-object relation. |
| side_a_instance_id required | string <uuid> |
| side_b_instance_id required | string <uuid> |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Retrieves a paginated list of relations for a given definition slug. Readable by users who can modify either definitions (DDL) or instances; the response carries the relation IDs needed to create instances with associations.
| definition_slug required | string Slug of the custom-object definition. |
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
EquipmentRelationsPage
{- "items": [
- {
- "id": "6f3d2a10-0000-4000-8000-000000000301",
- "a": {
- "definition_slug": "equipment",
- "cardinality": "ONE",
- "required": false,
- "slug": "maintenance_requests",
- "title": "Maintenance Requests",
- "is_hidden": false,
- "translations": {
- "en": {
- "singular": "Maintenance Request",
- "plural": "Maintenance Requests"
}, - "de": {
- "singular": "Wartungsanfrage",
- "plural": "Wartungsanfragen"
}
}
}, - "b": {
- "definition_slug": "maintenance_request",
- "cardinality": "MANY",
- "required": true,
- "slug": "equipment",
- "title": "Equipment",
- "is_hidden": false,
- "translations": {
- "en": {
- "singular": "Equipment",
- "plural": "Equipment"
}, - "de": {
- "singular": "Anlage",
- "plural": "Anlagen"
}
}
}, - "read_only": false
}
], - "page": {
- "size": 1,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Deletes a relation by its ID
| relation_id required | string <uuid> UUID of the custom-object relation. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Returns a page of webhook endpoints configured for the current tenant. Pass definition_id to return only endpoints whose stored subscription explicitly names that custom-object definition.
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
| definition_id | string <uuid> Example: definition_id=6b1e0f22-0000-4000-8000-000000000001 Return only endpoints holding a subscription scoped to this custom-object definition. Broader patterns such as |
AlpineWebhookEndpointsPage
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000008001",
- "display_name": "Alpine maintenance integration",
- "signature_scheme": "HMAC_SHA256",
- "enabled": true,
- "retry": true,
- "subscriptions": [
- "device.updated",
- "user.updated"
], - "invalid_subscriptions": [ ],
- "created_at": "2026-08-20T08:40:00Z",
- "updated_at": "2026-08-20T08:40:00Z",
- "lock_version": 0
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Creates a webhook endpoint with optional subscriptions and returns the generated secret once.
| display_name required | string [ 1 .. 255 ] characters Human readable endpoint name |
| endpoint_url required | string <uri> [ 1 .. 2048 ] characters ^https?://.+$ HTTPS destination URL. Plain HTTP is accepted only when the server's explicit local-development escape hatch is enabled. |
| signature_scheme | string Default: "HMAC_SHA256" Value: "HMAC_SHA256" Signature scheme |
| enabled | boolean Default: true Whether deliveries are enabled |
| retry | boolean Default: true Whether failed deliveries should be retried |
| subscriptions | Array of strings [ 0 .. 100 ] items [ items <= 512 characters ] Webhook event types to subscribe to |
CreateAlpineIntegrationEndpoint
{- "display_name": "Alpine maintenance integration",
- "signature_scheme": "HMAC_SHA256",
- "enabled": true,
- "retry": true,
- "subscriptions": [
- "device.updated",
- "user.updated"
]
}CreatedAlpineIntegrationEndpoint
{- "id": "00000000-0000-4000-8000-000000008001",
- "display_name": "Alpine maintenance integration",
- "signature_scheme": "HMAC_SHA256",
- "enabled": true,
- "retry": true,
- "subscriptions": [
- "device.updated",
- "user.updated"
], - "invalid_subscriptions": [ ],
- "created_at": "2026-08-20T08:40:00Z",
- "updated_at": "2026-08-20T08:40:00Z",
- "lock_version": 0,
- "secret": "whsec_example_not_a_real_secret"
}Rotates and returns a new secret. The previous secret is invalidated. The change takes effect immediately and the operation takes no request body.
| endpoint_id required | string <uuid> UUID of the webhook endpoint. |
RotatedAlpineIntegrationSecret
{- "id": "00000000-0000-4000-8000-000000008001",
- "display_name": "Alpine maintenance integration",
- "signature_scheme": "HMAC_SHA256",
- "enabled": true,
- "retry": true,
- "subscriptions": [
- "device.updated",
- "user.updated"
], - "invalid_subscriptions": [ ],
- "created_at": "2026-08-20T08:40:00Z",
- "updated_at": "2026-08-20T09:45:00Z",
- "lock_version": 2,
- "secret": "whsec_rotated_example_not_a_real_secret"
}Returns one webhook endpoint configured for the current tenant. The signing secret is never returned.
| endpoint_id required | string <uuid> UUID of the webhook endpoint. |
AlpineIntegrationEndpoint
{- "id": "00000000-0000-4000-8000-000000008001",
- "display_name": "Alpine maintenance integration",
- "signature_scheme": "HMAC_SHA256",
- "enabled": true,
- "retry": true,
- "subscriptions": [
- "device.updated",
- "user.updated"
], - "invalid_subscriptions": [ ],
- "created_at": "2026-08-20T08:40:00Z",
- "updated_at": "2026-08-20T08:40:00Z",
- "lock_version": 0
}Deletes a webhook endpoint and all its subscriptions.
| endpoint_id required | string <uuid> UUID of the webhook endpoint. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Partial update: omitted fields remain unchanged. Include subscriptions to replace them, or omit to keep existing subscriptions.
| endpoint_id required | string <uuid> UUID of the webhook endpoint. |
| display_name | string [ 1 .. 255 ] characters Human readable endpoint name. Omitted leaves the value unchanged. Explicit null and blank strings are rejected (422). |
| endpoint_url | string <uri> [ 1 .. 2048 ] characters HTTPS destination URL. Plain HTTP is accepted only when the server's explicit local-development escape hatch is enabled. Omitted leaves the value unchanged. Explicit null and blank strings are rejected (422). |
| signature_scheme | string Value: "HMAC_SHA256" Signature scheme. Omitted leaves the value unchanged. Explicit null is rejected (422). |
| enabled | boolean Whether deliveries are enabled. Omitted leaves the value unchanged. Explicit null is rejected (422). |
| retry | boolean Whether failed deliveries should be retried. Omitted leaves the value unchanged. Explicit null is rejected (422). |
| subscriptions | Array of strings <= 100 items [ items <= 512 characters ] Webhook event types to subscribe to. If provided, replaces all existing subscriptions. Omitted leaves the subscriptions unchanged. Explicit null is rejected (422). |
| lock_version | integer <int64> Optimistic lock version: validated when provided (409 on mismatch); omitting it skips the concurrency check. Explicit null is rejected (422). |
ReplaceIntegrationSubscriptions
{- "subscriptions": [
- "device.updated",
- "user.updated"
], - "lock_version": 0
}UpdatedAlpineIntegrationEndpoint
{- "id": "00000000-0000-4000-8000-000000008001",
- "display_name": "Alpine maintenance integration",
- "signature_scheme": "HMAC_SHA256",
- "enabled": true,
- "retry": true,
- "subscriptions": [
- "device.updated",
- "user.updated"
], - "invalid_subscriptions": [ ],
- "created_at": "2026-08-20T08:40:00Z",
- "updated_at": "2026-08-20T09:40:00Z",
- "lock_version": 1
}Immediately delivers a test webhook to the specified endpoint to verify connectivity
| endpoint_id required | string <uuid> Endpoint id to send a test webhook to |
TestAlpineIntegrationEndpoint
{- "endpoint_id": "00000000-0000-4000-8000-000000008001"
}SuccessfulAlpineWebhookTest
{- "last_test_tried_at": "2026-08-20T09:50:00Z",
- "test_was_successful": true
}Returns comments on the given target, paginated. sort follows the v2 <mode>:<direction> convention: threaded:desc (default — root comments newest-first; replies always oldest-first within each thread), threaded:asc, flat:desc, flat:asc. In threaded mode the page numbers refer to root comments and the response interleaves each root with its replies. Requires the comments read grant and read access to the target object.
| target_type required | string Example: target_type=bw:case Family-prefixed identifier of the object the comments are attached to. Examples: |
| target_id required | string <uuid> Example: target_id=22222222-2222-3333-4444-555555555555 Id of the target object the comments are attached to. |
| page | integer >= 0 Default: 0 Page number (0-based). In threaded mode this refers to the root-comment page. |
| size | integer [ 1 .. 1000 ] Default: 20 Example: size=20 Number of root comments per page (threaded) or items per page (flat). Range 1..1000. The 1000 cap is intentionally higher than the platform default (100) because the comments list is the primary read path for moderation, audit-log, and AI-assistant scrapes — workflows that need the full thread in one shot rather than paged. Frontends paginate at 20–50; the high cap is for server-side and integration callers. |
| sort | string Default: "threaded:desc" Enum: "threaded:desc" "threaded:asc" "flat:desc" "flat:asc" Example: sort=threaded:desc Sort instruction in |
EquipmentCommentsPage
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000007501",
- "target_type": "co:equipment",
- "target_id": "6f3d2a10-0000-4000-8000-000000000101",
- "root_comment_id": "00000000-0000-4000-8000-000000007501",
- "body_markdown": "Replacement filter ordered.",
- "author": {
- "id": "00000000-0000-4000-8000-000000001002",
- "first_name": "Jonas",
- "last_name": "Leitner",
- "is_deleted": false
}, - "created_at": "2026-03-03T10:45:00Z",
- "updated_at": "2026-03-03T10:45:00Z",
- "lock_version": 0,
- "is_edited": false,
- "is_moderated": false,
- "is_deleted": false,
- "is_deleted_by_moderator": false,
- "is_unread": false,
- "reactions": [ ],
- "mentions": [ ],
- "attachments": [ ]
}
], - "unread_count": 0,
- "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Creates a comment on the given target. Create access follows the target adapter for the supplied target_type. Server-side dedup: a duplicate submission by the same author against the same target with the same body within the configured window (default 60s) returns the existing comment with HTTP 200 instead of inserting a duplicate.
Both the 201 (fresh insert) and 200 (dedup) responses include a Location: /api/v2/comments/{comment_id} header pointing at the persisted row, per RFC 7231.
| target_type required | string non-empty Family-prefixed identifier of the object the comment is attached to. Examples: |
| target_id required | string <uuid> Id of the target object the comment is attached to. |
| parent_comment_id | string <uuid> Id of the parent comment when posting a reply. Must exist and belong to the same target. Omit (or send |
| body_markdown required | string [ 1 .. 10000 ] characters Comment body in markdown. Server enforces the v2 allow-list (bold, italic, strikethrough (GFM |
| attachment_ids | Array of strings <uuid> [ items <uuid > ] Filestore file ids previously obtained from |
CreateEquipmentMaintenanceComment
{- "target_type": "co:equipment",
- "target_id": "6f3d2a10-0000-4000-8000-000000000101",
- "body_markdown": "Replacement filter ordered."
}DeduplicatedFilterComment
{- "id": "00000000-0000-4000-8000-000000007501",
- "target_type": "co:equipment",
- "target_id": "6f3d2a10-0000-4000-8000-000000000101",
- "root_comment_id": "00000000-0000-4000-8000-000000007501",
- "body_markdown": "Replacement filter ordered.",
- "author": {
- "id": "00000000-0000-4000-8000-000000001002",
- "first_name": "Jonas",
- "last_name": "Leitner",
- "is_deleted": false
}, - "created_at": "2026-03-03T10:45:00Z",
- "updated_at": "2026-03-03T10:45:00Z",
- "lock_version": 0,
- "is_edited": false,
- "is_moderated": false,
- "is_deleted": false,
- "is_deleted_by_moderator": false,
- "is_unread": false,
- "reactions": [ ],
- "mentions": [ ],
- "attachments": [ ]
}Clears the soft-delete tombstone on a comment. Always a moderator action; requires the comments:update grant. Returns 422 when the comment is not currently soft-deleted (comments.cannot-restore-not-deleted).
| comment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Id of the soft-deleted comment to restore. |
RestoredFilterComment
{- "id": "00000000-0000-4000-8000-000000007501",
- "target_type": "co:equipment",
- "target_id": "6f3d2a10-0000-4000-8000-000000000101",
- "root_comment_id": "00000000-0000-4000-8000-000000007501",
- "body_markdown": "Replacement filter ordered.",
- "author": {
- "id": "00000000-0000-4000-8000-000000001002",
- "first_name": "Jonas",
- "last_name": "Leitner",
- "is_deleted": false
}, - "created_at": "2026-03-03T10:45:00Z",
- "updated_at": "2026-03-03T10:45:00Z",
- "lock_version": 0,
- "is_edited": false,
- "is_moderated": false,
- "is_deleted": false,
- "is_deleted_by_moderator": false,
- "is_unread": false,
- "reactions": [ ],
- "mentions": [ ],
- "attachments": [ ]
}Adds one of Tourfold's supported emoji reactions (👍 ❤️ 😂 🎉 😮 😢 👀 🙌) by the calling user to the named comment. Idempotent: 201 on the first add, 200 on a duplicate add (no row inserted, no SSE / webhook emitted). Tombstoned comments reject reactions with comments.reaction-on-deleted-comment (422).
| comment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Id of the comment to react to. |
| emoji required | string Enum: "👍" "❤️" "😂" "🎉" "😮" "😢" "👀" "🙌" Emoji to react with. Supported values are |
AddThumbsUp
{- "emoji": "👍"
}ExistingThumbsUpReaction
{- "id": "00000000-0000-4000-8000-000000007501",
- "target_type": "co:equipment",
- "target_id": "6f3d2a10-0000-4000-8000-000000000101",
- "root_comment_id": "00000000-0000-4000-8000-000000007501",
- "body_markdown": "Replacement filter ordered.",
- "author": {
- "id": "00000000-0000-4000-8000-000000001002",
- "first_name": "Jonas",
- "last_name": "Leitner",
- "is_deleted": false
}, - "created_at": "2026-03-03T10:45:00Z",
- "updated_at": "2026-03-03T10:45:00Z",
- "lock_version": 0,
- "is_edited": false,
- "is_moderated": false,
- "is_deleted": false,
- "is_deleted_by_moderator": false,
- "is_unread": false,
- "reactions": [
- {
- "emoji": "👍",
- "count": 1,
- "you_reacted": true,
- "your_reaction_id": "00000000-0000-4000-8000-000000007503"
}
], - "mentions": [ ],
- "attachments": [ ]
}Adds (or refreshes) the caller's unread override for the comment. The comment is then unread regardless of where the cursor sits. The cursor is not moved.
| comment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Id of the comment to mark unread. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Removes the caller's per-comment unread override, if any. Does not move the cursor. Idempotent: a no-op success when no override exists.
| comment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Id of the comment to clear the unread override on. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Sets the caller's read cursor on (target_type, target_id) to the named comment (inclusive). Monotonic — naming an older comment is a no-op success returning the existing cursor. As a side effect, clears the caller's per-comment unread overrides at-or-before the new cursor.
| target_type required | string non-empty Family-prefixed identifier of the object the cursor lives on. Examples: |
| target_id required | string <uuid> Id of the target object the cursor lives on. |
| comment_id required | string <uuid> Id of the comment the cursor should advance to (inclusive). The comment must belong to the supplied |
MarkEquipmentCommentsRead
{- "target_type": "co:equipment",
- "target_id": "6f3d2a10-0000-4000-8000-000000000101",
- "comment_id": "00000000-0000-4000-8000-000000007501"
}EquipmentCommentsReadCursor
{- "target_type": "co:equipment",
- "target_id": "6f3d2a10-0000-4000-8000-000000000101",
- "last_seen_comment_id": "00000000-0000-4000-8000-000000007501",
- "last_seen_created_at": "2026-03-03T10:45:00Z"
}Validates MIME / size / storage allowance and returns a presigned form descriptor. The client then POSTs the bytes to upload_url as multipart/form-data, including every entry from upload_fields (preserving their original order) followed by the actual file payload under the file part. The returned attachment_id is referenced later in POST /api/v2/comments (or PATCH /api/v2/comments/{comment_id}) via the attachment_ids array. No so_comment_attachments row is created at this point — files uploaded but never referenced are reaped asynchronously by the orphan-cleanup cron. Status is 200, not 201, because no addressable resource is exposed at a Location URL: the attachment_id is only meaningful once a subsequent comment create/edit references it. Requires the comments:create grant.
Not exposed via MCP — agents can't fill in presigned forms; the comments_create and comments_update MCP tools strip any attachment_ids from incoming payloads.
| original_file_name required | string [ 0 .. 255 ] characters Original filename to persist on the filestore blob. Surfaced back in the attachment chip and download Content-Disposition; users see this exact string. |
| mime_type required | string non-empty MIME type of the file. Almost any MIME is accepted; the server enforces a denylist ( |
| size_bytes required | string <int64> >= 1 File size in bytes. Must be > 0 and ≤ |
CreateFilterPhotoUpload
{- "original_file_name": "rtu-17-filter.jpg",
- "mime_type": "image/jpeg",
- "size_bytes": "248320"
}FilterPhotoUploadIntent
{- "attachment_id": "00000000-0000-4000-8000-000000007504",
- "upload_fields": {
- "key": "alpine/comments/rtu-17-filter.jpg",
- "policy": "example-not-a-real-policy"
}, - "expires_at": "2026-03-03T11:15:00Z"
}Returns one comment with its author and caller-scoped is_unread state. Used by the SSE-driven real-time wiring (the create event triggers a thin refetch to resolve the new author) and by deep-link openers that may target a comment which isn't on the currently visible list page. Requires the comments read grant and read access to the target object — the same gating as GET /api/v2/comments.
| comment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Id of the comment. |
EquipmentMaintenanceComment
{- "id": "00000000-0000-4000-8000-000000007501",
- "target_type": "co:equipment",
- "target_id": "6f3d2a10-0000-4000-8000-000000000101",
- "root_comment_id": "00000000-0000-4000-8000-000000007501",
- "body_markdown": "Replacement filter ordered.",
- "author": {
- "id": "00000000-0000-4000-8000-000000001002",
- "first_name": "Jonas",
- "last_name": "Leitner",
- "is_deleted": false
}, - "created_at": "2026-03-03T10:45:00Z",
- "updated_at": "2026-03-03T10:45:00Z",
- "lock_version": 0,
- "is_edited": false,
- "is_moderated": false,
- "is_deleted": false,
- "is_deleted_by_moderator": false,
- "is_unread": false,
- "reactions": [ ],
- "mentions": [ ],
- "attachments": [ ]
}Marks the comment as deleted. Author can delete own; users with the comments:delete grant can delete any. Idempotent: if the comment is already soft-deleted, the call is a no-op success. Soft-deleted comments stay in the list as tombstones with is_deleted=true and an empty body_markdown — the frontend renders a tombstone placeholder.
| comment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Id of the comment to soft-delete. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Updates a comment's body. Author can edit own; users with the comments:update grant can edit any. Moderator edits (caller != author) require a non-blank edit_reason — the server returns 422 (comments.moderation-reason-required) when missing. On success an audit row is appended to so_comment_edits in the same transaction; the response carries the updated comment with is_edited (and, for moderator edits, is_moderated) set to true.
Concurrency model: optional optimistic locking. Include the lock_version you last read to guard the edit — if it no longer matches the stored version the API returns 409 Conflict (resource-conflict); omit it (or send null) for last-write-wins, where the request that commits second overwrites the first. Either way every edit is appended to so_comment_edits as a separate audit row, so clients that need to reconcile can consult GET /api/v2/comments/{comment_id}/edits after their write.
| comment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Id of the comment to edit. |
| lock_version | integer or null <int64> Optimistic-locking version: validated when provided (409 on mismatch); omitting it skips the concurrency check |
| body_markdown | string New comment body in markdown. Omit to leave unchanged. Explicit |
| edit_reason | string or null Reason for the edit. Required (non-blank) when the caller is moderating another user's comment under the |
| attachment_ids | Array of strings or null <uuid> [ items <uuid > ] Replacement attachment list. Omit this field to leave the comment's attachments untouched — this is the typical case when the caller only wants to edit |
UpdateFilterComment
{- "body_markdown": "Replacement filter ordered for Friday.",
- "lock_version": 0
}UpdatedFilterComment
{- "id": "00000000-0000-4000-8000-000000007501",
- "target_type": "co:equipment",
- "target_id": "6f3d2a10-0000-4000-8000-000000000101",
- "root_comment_id": "00000000-0000-4000-8000-000000007501",
- "body_markdown": "Replacement filter ordered for Friday.",
- "author": {
- "id": "00000000-0000-4000-8000-000000001002",
- "first_name": "Jonas",
- "last_name": "Leitner",
- "is_deleted": false
}, - "created_at": "2026-03-03T10:45:00Z",
- "updated_at": "2026-03-03T11:00:00Z",
- "lock_version": 1,
- "last_edited_at": "2026-03-03T11:00:00Z",
- "is_edited": true,
- "is_moderated": false,
- "is_deleted": false,
- "is_deleted_by_moderator": false,
- "is_unread": false,
- "reactions": [ ],
- "mentions": [ ],
- "attachments": [ ]
}Computes which page of GET /api/v2/comments contains [id] under the given sort + size. Used by deep-link openers (frontend ?commentId=…) to jump straight to the right page without paginating one click at a time. In threaded mode the returned page is the page of root comments; if the target is a reply, its row appears under its root on that page. Requires the comments read grant and read access to the target object — the same gating as the list endpoint.
| comment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Id of the comment to locate. |
| sort | string Default: "threaded:desc" Enum: "threaded:desc" "threaded:asc" "flat:desc" "flat:asc" Example: sort=threaded:desc Same |
| size | integer [ 1 .. 1000 ] Default: 20 Example: size=20 Page size used for the index calculation. Must match the |
EquipmentCommentPageInfo
{- "comment_id": "00000000-0000-4000-8000-000000007501",
- "root_comment_id": "00000000-0000-4000-8000-000000007501",
- "mode": "threaded",
- "page": 0,
- "total_pages": 1
}Returns the ordered audit trail for a single comment, newest-first. Each entry includes the editor reference, the body as it stood before the edit, the (moderator) edit_reason, the per-edit attachment-name diff (attachments_added_names / attachments_removed_names), and is_moderation (derived from editor.id != author.id). Requires the comments:update grant.
| comment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Id of the comment. |
FilterCommentEditHistory
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000007502",
- "edited_at": "2026-03-03T11:00:00Z",
- "editor": {
- "id": "00000000-0000-4000-8000-000000001002",
- "first_name": "Jonas",
- "last_name": "Leitner",
- "is_deleted": false
}, - "previous_body_markdown": "Replacement filter ordered.",
- "is_moderation": false,
- "attachments_added_names": [ ],
- "attachments_removed_names": [ ]
}
]
}Returns email + roles (and equivalent richer fields for future types) so the read-path mention popover can render without a second round-trip. Auth only — every logged-in user can resolve mention details on comments they can read.
Deleted targets return 200 with is_deleted=true and best-effort cached data (display name, roles, email-at-time-of-deletion). This deviates from strict REST semantics — a 404 / 410 would lose the cached fields the popover renders as 'deleted user — last known: is_deleted before treating the response as a live target. Unknown ids (e.g. cross-tenant) return 404 comments/mention-target-not-found.
| target_type required | string Value: "user" Example: user Mention-type discriminator. |
| target_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Target id. |
AlpineUserMentionDetail
{- "type": "user",
- "id": "00000000-0000-4000-8000-000000000102",
- "display_name": "Jonas Leitner",
- "is_deleted": false,
- "email": "jonas.leitner@example.invalid",
- "roles": [
- "Field Technician"
]
}Returns up to limit mention targets matching search for the requested target_type. Ranked: prefix-matches first (alpha-sorted within), substring matches second (alpha-sorted within). Empty search returns the top-N targets alpha-sorted. Requires the comments:create grant — read-only viewers never need the picker. Tenant scope is enforced by the schema interceptor.
| search | string Example: search=ali Free-text query. Matches against first / last name and email for user mentions. Empty / missing → top-N alpha-sorted. |
| target_type | string Example: target_type=user Mention-type discriminator to search. Currently only |
| limit | integer [ 1 .. 50 ] Default: 10 Example: limit=10 Maximum number of suggestions to return. Range 1..50. |
AlpineUserMentionSuggestions
{- "items": [
- {
- "type": "user",
- "id": "00000000-0000-4000-8000-000000000102",
- "display_name": "Jonas Leitner",
- "secondary_text": "jonas.leitner@example.invalid"
}
]
}Returns total and caller-scoped unread counts for every requested target the caller may read, preserving request order. Readable targets with no comments receive explicit zero counts. Missing and unreadable targets are omitted without revealing whether they exist. Tombstones are excluded from both counts.
| target_type required | string Example: target_type=bw:case Family-prefixed identifier of the object the comments are attached to. Examples: |
| target_ids required | Array of strings <uuid> [ 1 .. 100 ] items [ items <uuid > ] Example: target_ids=22222222-2222-3333-4444-555555555555 Target ids to count for. Supply 1 to 100 UUIDs by repeating the plural |
EquipmentCommentCounts
{- "items": [
- {
- "target_type": "co:equipment",
- "target_id": "6f3d2a10-0000-4000-8000-000000000101",
- "count": 1,
- "unread_count": 0
}
]
}Presigned URLs returned on the comment list endpoint expire after comments.attachments.download-url-ttl-seconds (default 5 min). This endpoint refreshes them for a single attachment — used by the preview modal when the user opens a chip / inline image long after the comment was first rendered.
Authorisation gate: the caller must be authenticated in the tenant and the parent comment must exist and be live (not soft-deleted) — Phase 5 will additionally enforce target-object read access.
Error contract:
comments/attachment-not-found when no attachment row matches the id, when its parent comment was hard-deleted (FK cascade drops the row), or when the parent comment has been soft-deleted.comments/attachment-blob-gone when the row exists but the underlying filestore blob has been hard-deleted (target cascade, manual purge, orphan-cleanup gap). The client should NOT retry; the list endpoint still surfaces the row with is_deleted=true so the comment body keeps its placeholder chip.| attachment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Comment attachment id. |
FilterPhotoDownloadUrls
{- "expires_at": "2026-03-03T11:20:00Z"
}Removes the calling user's reaction row addressed by the opaque {reaction_id} (read from reactions[*].your_reaction_id on a recent CommentResponse). Returns the updated comment. 404 comments/reaction-not-found when the id does not exist OR belongs to a different user — both cases return the same problem so the surface doesn't leak the existence of other users' reaction rows. The path id (rather than the emoji) avoids the fragile URL-encoding of skin-tone modifiers, ZWJ sequences, and similar. Removal uses the stored value without reparsing it so historical or manually repaired rows remain cleanable.
| comment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Id of the comment to un-react from. Used only for routing — the reaction id alone is sufficient to identify the row to remove. |
| reaction_id required | string <uuid> Example: 33333333-aaaa-bbbb-cccc-dddddddddddd Opaque id of the caller's reaction row. Read from |
CommentWithoutReaction
{- "id": "00000000-0000-4000-8000-000000007501",
- "target_type": "co:equipment",
- "target_id": "6f3d2a10-0000-4000-8000-000000000101",
- "root_comment_id": "00000000-0000-4000-8000-000000007501",
- "body_markdown": "Replacement filter ordered.",
- "author": {
- "id": "00000000-0000-4000-8000-000000001002",
- "first_name": "Jonas",
- "last_name": "Leitner",
- "is_deleted": false
}, - "created_at": "2026-03-03T10:45:00Z",
- "updated_at": "2026-03-03T10:45:00Z",
- "lock_version": 0,
- "is_edited": false,
- "is_moderated": false,
- "is_deleted": false,
- "is_deleted_by_moderator": false,
- "is_unread": false,
- "reactions": [ ],
- "mentions": [ ],
- "attachments": [ ]
}Marks the filestore blob as deleted so storage is reclaimed immediately when the user changes their mind about an attachment in the composer (clicks the pill ✕ before posting the comment). Without this endpoint, abandoned uploads sit on filestore for up to comments.attachments.orphan-retention-hours (default 24) before the nightly orphan-cleanup task sweeps them.
Idempotent. Repeated DELETEs return 204; the second call is a no-op on an already-deleted file.
Scope. Only deletes files whose source_key is COMMENT_ATTACHMENTS AND that are NOT yet linked to a posted comment. Once a file is part of so_comment_attachments the proper removal path is the comment-delete endpoint (which cascades blob removal via the comment hard-delete hook).
Authorisation gate. Requires the comments:create grant — same as the upload-intent endpoint. There is no per-uploader check: filestore does not track uploader identity and UUID-unguessability + schema-per-tenant isolation are the gates against cross-user / cross-tenant abuse, matching the orphan-cleanup task's posture (which also treats every unreferenced file the same way regardless of who uploaded it).
Not exposed via MCP — abandoned-upload cleanup is a UI-driven affordance and the agent surface doesn't have a use case for it.
| attachment_id required | string <uuid> Example: 11111111-aaaa-bbbb-cccc-dddddddddddd Comment attachment id of the abandoned upload. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Manage SMS gateway configurations per tenant. Gateways are evaluated by priority (0 = primary) for failover.
Returns gateways ordered by priority (0 = primary). Disabled gateways are included.
GatewaysList
{- "items": [
- {
- "id": "11111111-2222-3333-4444-555555555555",
- "name": "Primary Twilio",
- "type": "TWILIO",
- "priority": 0,
- "enabled": true,
- "lock_version": 0,
- "twilio_config": {
- "username": "twilio-user-example",
- "auth_token": "twilio-auth-token-example",
- "account_sid": "AC00000000000000000000000000000000",
- "account_auth_token": "account-auth-token-example",
- "messaging_service_sid": "MG00000000000000000000000000000000",
- "phone_number": "+436641234567"
}
}, - {
- "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
- "name": "Fallback Custom",
- "type": "CUSTOM_HTTP",
- "priority": 1,
- "enabled": false,
- "lock_version": 0,
- "custom_config": {
- "http_method": "POST",
- "content_type": "application/json",
- "auth_method": "NONE",
- "parameters": [ ]
}
}
]
}Creates a tenant SMS gateway and returns its effective priority and configuration.
| name required | string non-empty Tenant-visible gateway name. |
| type required | string Enum: "TWILIO" "CUSTOM_HTTP" Gateway integration type. |
| priority | integer <int32> >= 0 Requested zero-based failover position. Omit to append the gateway. |
| enabled | boolean Default: true Whether the gateway may be used immediately. Defaults to true. |
object (TwilioGatewayConfig) Required when type is TWILIO; omit for CUSTOM_HTTP. | |
object (CustomSmsSettings) Required when type is CUSTOM_HTTP; omit for TWILIO. |
CreateAlpineTwilioGateway
{- "name": "Alpine primary SMS",
- "type": "TWILIO",
- "priority": 0,
- "enabled": true,
- "twilio_config": {
- "username": "twilio-user-example",
- "auth_token": "twilio-auth-token-example",
- "account_sid": "AC00000000000000000000000000000000",
- "account_auth_token": "account-auth-token-example",
- "messaging_service_sid": "MG00000000000000000000000000000000",
- "phone_number": "+43 664 123 45 67"
}
}CreateTwilioGateway
{- "id": "11111111-2222-3333-4444-555555555555",
- "name": "Primary Twilio",
- "type": "TWILIO",
- "priority": 0,
- "enabled": true,
- "lock_version": 0,
- "twilio_config": {
- "username": "twilio-user-example",
- "auth_token": "twilio-auth-token-example",
- "account_sid": "AC00000000000000000000000000000000",
- "account_auth_token": "account-auth-token-example",
- "messaging_service_sid": "MG00000000000000000000000000000000",
- "phone_number": "+436641234567"
}
}Queues a test message through the selected gateway and returns its tracking id.
| sms_gateway_id required | string <uuid> Gateway identifier |
| phone_number required | string non-empty International recipient number with an explicit '+' country code. Formatted input is normalized to E.164. |
SendTechnicianTestSms
{- "phone_number": "+436641234567"
}TestSmsAccepted
{- "tracking_id": "00000000-0000-4000-8000-000000004901"
}Reorders all gateways for the current tenant; request must list every gateway exactly once in the desired order (0 = primary).
| gateway_ids required | Array of strings <uuid> non-empty [ items <uuid > ] |
PrioritizeGateways
{- "gateway_ids": [
- "11111111-2222-3333-4444-555555555555",
- "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
]
}{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Returns the full gateway configuration for the given ID.
| sms_gateway_id required | string <uuid> Gateway identifier |
GatewayResponse
{- "id": "11111111-2222-3333-4444-555555555555",
- "name": "Primary Twilio",
- "type": "TWILIO",
- "priority": 0,
- "enabled": true,
- "lock_version": 0,
- "twilio_config": {
- "username": "twilio-user-example",
- "auth_token": "twilio-auth-token-example",
- "account_sid": "AC00000000000000000000000000000000",
- "account_auth_token": "account-auth-token-example",
- "messaging_service_sid": "MG00000000000000000000000000000000",
- "phone_number": "+436641234567"
}
}Permanently removes the tenant SMS gateway.
| sms_gateway_id required | string <uuid> Gateway identifier |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Allows partial updates (name, enabled flag, priority).
| sms_gateway_id required | string <uuid> Gateway identifier |
| lock_version | integer or null <int64> Optimistic-locking version: validated when provided (409 on mismatch); omitting it skips the concurrency check |
| name | string Display name of the gateway. Omitted leaves the value unchanged; explicit null is rejected (422) — it cannot be cleared. |
| enabled | boolean Whether the gateway is enabled. Omitted leaves the value unchanged; explicit null is rejected (422) — it cannot be cleared. |
| priority | integer <int32> Evaluation priority (0 = primary). Omitted leaves the value unchanged; explicit null is rejected (422) — it cannot be cleared. |
object (TwilioGatewayConfig) Replaces the whole Twilio configuration when provided (gateway must be of type TWILIO). Omitted leaves the configuration unchanged; explicit null is rejected (422). | |
object (CustomSmsSettings) Replaces the whole custom-HTTP configuration when provided (gateway must be of type CUSTOM_HTTP). Omitted leaves the configuration unchanged; explicit null is rejected (422). |
DisableGateway
{- "lock_version": 0,
- "enabled": false
}UpdateGateway
{- "id": "11111111-2222-3333-4444-555555555555",
- "name": "Renamed Gateway",
- "type": "TWILIO",
- "priority": 0,
- "enabled": false,
- "lock_version": 1,
- "twilio_config": {
- "username": "twilio-user-example",
- "auth_token": "twilio-auth-token-example",
- "account_sid": "AC00000000000000000000000000000000",
- "account_auth_token": "account-auth-token-example",
- "messaging_service_sid": "MG00000000000000000000000000000000",
- "phone_number": "+436641234567"
}
}Retrieve a paginated list of webhook delivery failures for the current tenant.
A row represents the latest recorded failed attempt for one webhook message. The same row is updated when another retry fails, while the first and latest failure timestamps remain available. This endpoint is not a full delivery or per-attempt audit ledger: successful attempts and deliveries skipped before an HTTP request are not recorded. A successful retry after an earlier failure does not add a success record, so absence does not prove success and presence alone does not prove the message ultimately failed.
Use the filters to narrow down results by time range, endpoint, or event type.
Requires any of 'webhooks:read', 'webhooks:create', or 'webhooks:update' grant.
| page | integer >= 0 Default: 0 Page number (0-based). First page is 0. |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page. Maximum allowed is 100. |
| failed_from | string <date-time> Example: failed_from=2024-01-01T00:00:00Z Return failures whose first failed attempt occurred at or after this RFC 3339 timestamp (inclusive). |
| failed_to | string <date-time> Example: failed_to=2025-01-01T00:00:00Z Return failures whose first failed attempt occurred before this RFC 3339 timestamp (exclusive). |
| endpoint_id | string <uuid> Example: endpoint_id=019bb29d-2458-722e-b21b-679e632ca96b Filter by specific webhook endpoint ID. |
| event_type | string Example: event_type=area.created Filter by event type. |
| sort | string Default: "first_attempt_failed_at:desc" Example: sort=first_attempt_failed_at:desc Single sorting criterion in |
DeliveryFailuresResponse
{- "items": [
- {
- "id": "f8c1b4b5-ffe8-4d1c-8f0a-8c55e7b9c6d1",
- "message_id": "a1b2c3d4-e5f6-4a1b-8c9d-123456789abc",
- "endpoint_id": "019bb29d-2458-722e-b21b-679e632ca96b",
- "event_type": "area.created",
- "attempt": 3,
- "retries_remaining": 4,
- "will_retry": true,
- "retry_state": "RETRYING",
- "http_status_code": 500,
- "error_message": "HTTP 500: Internal Server Error",
- "first_attempt_failed_at": "2024-11-10T10:00:00Z",
- "latest_retry_attempt_failed_at": "2024-11-10T10:30:00Z"
}, - {
- "id": "a83f3f6c-6d3b-4f3a-89d7-1d3c9d0f1c2b",
- "message_id": "b2c3d4e5-f6a7-4b1c-9d0e-234567890bcd",
- "endpoint_id": "019bb29d-2458-722e-b21b-679e632ca96b",
- "event_type": "area.updated",
- "attempt": 10,
- "retries_remaining": 0,
- "will_retry": false,
- "retry_state": "EXHAUSTED",
- "error_message": "Connection timed out",
- "first_attempt_failed_at": "2024-11-09T12:00:00Z",
- "latest_retry_attempt_failed_at": "2024-11-09T15:45:00Z"
}
], - "page": {
- "size": 20,
- "total_elements": 2,
- "total_pages": 1,
- "number": 0
}
}Retrieves a custom object definition by slug
| definition_slug required | string Slug of the custom-object definition. |
EquipmentDefinition
{- "id": "6f3d2a10-0000-4000-8000-000000000001",
- "schema": {
- "slug": "equipment",
- "title": "Equipment",
- "displayTemplate": "{{name}} · {{asset_tag}}",
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
}, - "asset_tag": {
- "type": "string"
}, - "serial_number": {
- "type": "string"
}, - "category": {
- "type": "string",
- "enum": [
- "hvac",
- "elevator",
- "lighting"
]
}, - "installed_at": {
- "type": "string",
- "format": "date-time"
}, - "active": {
- "type": "boolean"
}
}, - "required": [
- "name",
- "asset_tag",
- "serial_number",
- "category",
- "installed_at",
- "active"
], - "additionalProperties": false
}, - "created_at": "2026-03-01T08:00:00Z",
- "updated_at": "2026-03-03T10:20:00Z",
- "lock_version": 5,
- "effective_access_level": "manage"
}Updates an existing custom object definition.
| definition_slug required | string Slug of the custom-object definition. |
| lock_version | integer <int64> Optimistic-locking version: validated when provided (409 on mismatch); omitting it skips the concurrency check |
required | object (CustomObjectSchemaInput) Updated JSON Schema definition |
ReplaceEquipmentDefinition
{- "lock_version": 3,
- "schema": {
- "title": "Equipment",
- "description": "Building equipment maintained by Alpine Facility Services GmbH",
- "displayTemplate": "{{name}} · {{asset_tag}}",
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
}, - "asset_tag": {
- "type": "string"
}, - "serial_number": {
- "type": "string"
}, - "category": {
- "type": "string",
- "enum": [
- "hvac",
- "elevator",
- "lighting"
]
}, - "installed_at": {
- "type": "string",
- "format": "date-time"
}, - "active": {
- "type": "boolean"
}, - "next_service_at": {
- "type": "string",
- "format": "date-time"
}, - "specifications": {
- "type": "object",
- "properties": {
- "manufacturer": {
- "type": "string"
}, - "model": {
- "type": "string"
}, - "power_kw": {
- "type": "number"
}
}
}, - "supported_services": {
- "type": "array",
- "items": {
- "type": "string"
}
}
}, - "required": [
- "name",
- "asset_tag",
- "serial_number",
- "category",
- "installed_at",
- "active"
], - "additionalProperties": false,
- "translations": {
- "en": {
- "singular": "Equipment",
- "plural": "Equipment"
}, - "de": {
- "singular": "Anlage",
- "plural": "Anlagen"
}
}
}
}ReplacedEquipmentDefinition
{- "id": "6f3d2a10-0000-4000-8000-000000000001",
- "schema": {
- "slug": "equipment",
- "title": "Equipment",
- "displayTemplate": "{{name}} · {{asset_tag}}",
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
}, - "asset_tag": {
- "type": "string"
}, - "serial_number": {
- "type": "string"
}, - "category": {
- "type": "string",
- "enum": [
- "hvac",
- "elevator",
- "lighting"
]
}, - "installed_at": {
- "type": "string",
- "format": "date-time"
}, - "active": {
- "type": "boolean"
}, - "next_service_at": {
- "type": "string",
- "format": "date-time"
}
}, - "required": [
- "name",
- "asset_tag",
- "serial_number",
- "category",
- "installed_at",
- "active"
], - "additionalProperties": false
}, - "created_at": "2026-03-01T08:00:00Z",
- "updated_at": "2026-03-03T10:15:00Z",
- "lock_version": 4,
- "effective_access_level": "manage"
}Deletes a custom object definition including its database table.
| definition_slug required | string Slug of the custom-object definition. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Updates only the display template of a custom object definition. The display template is a presentation-only field, so this is permitted for built-in and read-only system definitions whose schema structure cannot otherwise be modified.
| definition_slug required | string Slug of the custom-object definition. |
| lock_version | integer <int64> Optimistic-locking version: validated when provided (409 on mismatch); omitting it skips the concurrency check |
| display_template | string Display template: free text interleaved with |
SetEquipmentDisplayTemplate
{- "lock_version": 4,
- "display_template": "{{name}} · {{asset_tag}}"
}EquipmentDisplayTemplateUpdated
{- "id": "6f3d2a10-0000-4000-8000-000000000001",
- "schema": {
- "slug": "equipment",
- "title": "Equipment",
- "displayTemplate": "{{name}} · {{asset_tag}}",
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
}, - "asset_tag": {
- "type": "string"
}, - "serial_number": {
- "type": "string"
}, - "category": {
- "type": "string",
- "enum": [
- "hvac",
- "elevator",
- "lighting"
]
}, - "installed_at": {
- "type": "string",
- "format": "date-time"
}, - "active": {
- "type": "boolean"
}
}, - "required": [
- "name",
- "asset_tag",
- "serial_number",
- "category",
- "installed_at",
- "active"
], - "additionalProperties": false
}, - "created_at": "2026-03-01T08:00:00Z",
- "updated_at": "2026-03-03T10:20:00Z",
- "lock_version": 5,
- "effective_access_level": "manage"
}Retrieves all custom object definitions
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
| read_only | boolean Filter definitions by their read-only flag. Pass |
| built_in | boolean Filter definitions by their built-in flag. Pass |
EquipmentDefinitionsPage
{- "items": [
- {
- "id": "6f3d2a10-0000-4000-8000-000000000001",
- "schema": {
- "slug": "equipment",
- "title": "Equipment",
- "displayTemplate": "{{name}} · {{asset_tag}}",
- "type": "object"
}, - "created_at": "2026-03-01T08:00:00Z",
- "updated_at": "2026-03-03T10:20:00Z",
- "lock_version": 5,
- "effective_access_level": "manage"
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Creates a new custom object definition.
required | object (CustomObjectSchemaInput) JSON Schema definition |
Array of objects (RelationSchema) Relations to create along with this definition |
CreateEquipmentDefinition
{- "schema": {
- "title": "Equipment",
- "description": "Building equipment maintained by Alpine Facility Services GmbH",
- "displayTemplate": "{{name}} · {{asset_tag}}",
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
}, - "asset_tag": {
- "type": "string"
}, - "serial_number": {
- "type": "string"
}, - "category": {
- "type": "string",
- "enum": [
- "hvac",
- "elevator",
- "lighting"
]
}, - "installed_at": {
- "type": "string",
- "format": "date-time"
}, - "active": {
- "type": "boolean"
}, - "specifications": {
- "type": "object",
- "properties": {
- "manufacturer": {
- "type": "string"
}, - "model": {
- "type": "string"
}, - "power_kw": {
- "type": "number"
}
}
}, - "supported_services": {
- "type": "array",
- "items": {
- "type": "string"
}
}
}, - "required": [
- "name",
- "asset_tag",
- "serial_number",
- "category",
- "installed_at",
- "active"
], - "additionalProperties": false,
- "translations": {
- "en": {
- "singular": "Equipment",
- "plural": "Equipment"
}, - "de": {
- "singular": "Anlage",
- "plural": "Anlagen"
}
}
}
}CreatedEquipmentDefinition
{- "id": "6f3d2a10-0000-4000-8000-000000000001",
- "schema": {
- "slug": "equipment",
- "title": "Equipment",
- "displayTemplate": "{{name}} · {{asset_tag}}",
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
}, - "asset_tag": {
- "type": "string"
}, - "serial_number": {
- "type": "string"
}, - "category": {
- "type": "string",
- "enum": [
- "hvac",
- "elevator",
- "lighting"
]
}, - "installed_at": {
- "type": "string",
- "format": "date-time"
}, - "active": {
- "type": "boolean"
}
}, - "required": [
- "name",
- "asset_tag",
- "serial_number",
- "category",
- "installed_at",
- "active"
], - "additionalProperties": false
}, - "created_at": "2026-03-01T08:00:00Z",
- "updated_at": "2026-03-01T08:00:00Z",
- "lock_version": 0,
- "effective_access_level": "manage"
}Returns measure units ordered by name, paginated.
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
CapacityUnitsPage
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000006501",
- "name": "Kilograms",
- "symbol": "kg",
- "created_at": "2026-08-20T08:20:00Z",
- "updated_at": "2026-08-20T08:20:00Z",
- "lock_version": 0
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Creates a tenant measure unit with a unique name and symbol.
| name required | string non-empty Human-readable name, e.g. "Kilogram" |
| symbol required | string non-empty Symbol, e.g. "kg" |
CreateKilogramsUnit
{- "name": "Kilograms",
- "symbol": "kg"
}CreatedKilogramsUnit
{- "id": "00000000-0000-4000-8000-000000006501",
- "name": "Kilograms",
- "symbol": "kg",
- "created_at": "2026-08-20T08:20:00Z",
- "updated_at": "2026-08-20T08:20:00Z",
- "lock_version": 0
}Returns one tenant measure unit by its UUID.
| measure_unit_id required | string <uuid> UUID of the measure unit. |
KilogramsUnit
{- "id": "00000000-0000-4000-8000-000000006501",
- "name": "Kilograms",
- "symbol": "kg",
- "created_at": "2026-08-20T08:20:00Z",
- "updated_at": "2026-08-20T08:20:00Z",
- "lock_version": 0
}Permanently removes a tenant measure unit.
| measure_unit_id required | string <uuid> UUID of the measure unit. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Partial update: omitted fields remain unchanged.
| measure_unit_id required | string <uuid> UUID of the measure unit. |
| name | string Human-readable name, e.g. "Kilogram". Omitted leaves the value unchanged. Explicit null is rejected (422) — name is required and cannot be cleared. |
| symbol | string Symbol, e.g. "kg". Omitted leaves the value unchanged. Explicit null is rejected (422) — symbol is required and cannot be cleared. |
| lock_version | integer or null <int64> Lock version for optimistic locking |
UpdateKilogramsName
{- "name": "Kilograms (kg)",
- "lock_version": 0
}UpdatedKilogramsUnit
{- "id": "00000000-0000-4000-8000-000000006501",
- "name": "Kilograms (kg)",
- "symbol": "kg",
- "created_at": "2026-08-20T08:20:00Z",
- "updated_at": "2026-08-20T09:20:00Z",
- "lock_version": 1
}Pulls the tenant's live subscription status from Stripe and updates the stored billing standing, then returns the refreshed decision. Acts as a fallback when a Stripe webhook has not yet arrived — e.g. a user who just updated their payment method on the billing-locked screen and wants to unlock immediately. Reachable while the tenant is billing-locked.
ActiveAlpineBilling
{- "allowed": true,
- "status": "ACTIVE"
}Returns a one-time URL the client should redirect the user to so they can manage their payment method in Stripe's hosted Customer Portal. The tenant must already have a Stripe customer (paid plan).
| return_url required | string [ 0 .. 2048 ] characters Absolute URL the customer is redirected to after closing the Stripe Customer Portal. The origin must match the tenant's primary domain or one of its configured custom domains. |
CreateAlpineBillingPortalSession
{
}AlpineBillingPortalSession
Returns a summary (brand, last4, expiry) of the default payment method attached to the tenant's Stripe customer. The has_payment_method flag is false when no card is on file yet.
AlpinePaymentMethod
{- "has_payment_method": true,
- "brand": "visa",
- "last4": "4242",
- "exp_month": 12,
- "exp_year": 2028
}Creates a presigned upload form for a new tenant logo.
| original_file_name required | string non-empty Original filename |
| mime_type required | string non-empty MIME type |
CreateTenantLogoUpload
{- "original_file_name": "alpine-facility-services-logo.svg",
- "mime_type": "image/svg+xml"
}AlpineTenantLogoUpload
{- "file_id": "00000000-0000-4000-8000-000000000701",
- "upload_fields": {
- "key": "alpine/tenant-logo.svg",
- "policy": "example-not-a-real-policy"
}, - "expires_at_utc": "2026-08-20T10:15:00Z"
}Creates a presigned upload form for a new tenant favicon.
| original_file_name required | string non-empty Original filename |
| mime_type required | string non-empty MIME type |
CreateTenantFaviconUpload
{- "original_file_name": "alpine-favicon.png",
- "mime_type": "image/png"
}AlpineTenantFaviconUpload
{- "file_id": "00000000-0000-4000-8000-000000000702",
- "upload_fields": {
- "key": "alpine/favicon.png",
- "policy": "example-not-a-real-policy"
}, - "expires_at_utc": "2026-08-20T10:15:00Z"
}JSON Merge Patch (RFC 7386). Omitted fields remain unchanged.
| name | string <= 255 characters Tenant name. Omitted leaves the value unchanged; explicit null is rejected (422). |
| language | string <= 10 characters Tenant content language tag. Legacy locale-style values such as en-US are accepted and normalized. Omitted leaves the value unchanged; explicit null is rejected (422). |
| region | string <= 2 characters Tenant region as ISO 3166-1 alpha-2 country code. Omitted leaves the value unchanged; explicit null is rejected (422). |
| timezone | string <= 50 characters Tenant timezone as IANA timezone identifier. Omitted leaves the value unchanged; explicit null is rejected (422). |
| lock_version | integer or null <int64> Optimistic-locking version: validated when provided (409 on mismatch); omitting it skips the concurrency check. |
UpdateName
{- "name": "Alpine Facility Services GmbH",
- "lock_version": 0
}UpdatedAlpineTenant
{- "name": "Alpine Facility Services GmbH",
- "language": "de",
- "region": "AT",
- "timezone": "Europe/Vienna",
- "lock_version": 0
}Removes the current tenant logo. Repeating the request is safe.
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Returns upload and application status for a tenant logo upload intent.
| file_id required | string <uuid> UUID of the uploaded file. |
UploadedAlpineTenantLogo
{- "file_id": "00000000-0000-4000-8000-000000000701",
- "status": "UPLOADED",
- "applied": true,
}Removes the current tenant favicon. Repeating the request is safe.
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Returns upload and application status for a tenant favicon upload intent.
| file_id required | string <uuid> UUID of the uploaded file. |
UploadedAlpineTenantFavicon
{- "file_id": "00000000-0000-4000-8000-000000000702",
- "status": "UPLOADED",
- "applied": true,
}Returns the current AI assistant operating mode for this tenant.
ReadOnlyAssistantSettings
{- "mode": "READ_ONLY",
- "enabled": true,
- "tool_mode": "READ_ONLY",
- "tenant_id": "00000000-0000-4000-8000-000000000001"
}Updates the AI assistant mode. OFF disables the assistant, READ_ONLY enables read-only tools, and READ_WRITE enables read and write-capable tools.
| mode | string Enum: "OFF" "READ_ONLY" "READ_WRITE" New assistant mode. OFF disables the assistant, READ_ONLY enables read-only tool access, READ_WRITE enables read and write-capable tool access. Omit to leave unchanged; explicit null is rejected (422). |
EnableReadOnlyAssistant
{- "mode": "READ_ONLY"
}UpdatedReadOnlyAssistantSettings
{- "mode": "READ_ONLY",
- "enabled": true,
- "tool_mode": "READ_ONLY",
- "tenant_id": "00000000-0000-4000-8000-000000000001"
}Returns a paginated list of devices with their latest telemetry snapshot.
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Number of items per page (max 100). |
| sort | Array of strings Example: sort=natural_id:asc Repeated sorting criteria in |
| search | string Search term for model, identity, phone number, or description. |
| model | string Filter by device model (case-insensitive substring match). |
| kind | string Enum: "TOURFOLD_APP" "THIRD_PARTY_OSMAND" "TRACKING_DEVICE" Filter by device kind. |
| has_location | boolean Filter to devices with or without a latest location. |
| updated_from | string <date-time> Filter to devices updated at or after this timestamp. |
| updated_to | string <date-time> Filter to devices updated before this timestamp. |
| include | Array of strings Items Value: "current_state" Example: include=current_state Optional related resources to embed. Supported: |
| min_lat | number <double> [ -90 .. 90 ] Latest-location bounding box: minimum latitude. All four bbox corners must be supplied together. |
| min_lon | number <double> [ -180 .. 180 ] Latest-location bounding box: minimum longitude. All four bbox corners must be supplied together. |
| max_lat | number <double> [ -90 .. 90 ] Latest-location bounding box: maximum latitude. All four bbox corners must be supplied together. |
| max_lon | number <double> [ -180 .. 180 ] Latest-location bounding box: maximum longitude. All four bbox corners must be supplied together. |
TechnicianDevicesPage
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000004001",
- "created_at": "2026-08-20T08:00:00Z",
- "updated_at": "2026-08-20T08:00:00Z",
- "lock_version": 0,
- "natural_id": 17,
- "kind": "TOURFOLD_APP",
- "device_model": "Pixel 9",
- "device_identity_id": "jonas-pixel-9",
- "provisioning_state": "PROVISIONED",
- "phone_number": "+436641234567",
- "platform": "ANDROID",
- "description": "Jonas Leitner's service device"
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Creates a device. Provisioning state is system-managed and is not accepted in this request.
| kind | string Enum: "TOURFOLD_APP" "THIRD_PARTY_OSMAND" "TRACKING_DEVICE" Device kind. Defaults to TOURFOLD_APP when omitted. |
| device_model | string [ 0 .. 128 ] characters Human-readable model or tracker type |
| device_identity_id | string [ 0 .. 255 ] characters Stable device identifier such as a generated app installation id, OsmAnd id, or tracker protocol id |
| connection_profile | string [ 0 .. 128 ] characters Provider connection profile selected for tracking hardware, for example OSMAND_HTTP_ONLY |
| phone_number | string [ 0 .. 32 ] characters International phone number. An explicit '+' country code is required; common formatting is accepted and normalized to canonical E.164. National numbers are rejected. |
| platform | string Enum: "UNKNOWN" "IOS" "ANDROID" Mobile platform when known |
| description | string [ 0 .. 2048 ] characters Optional operator notes |
CreateTechnicianDevice
{- "kind": "TOURFOLD_APP",
- "device_model": "Pixel 9",
- "device_identity_id": "jonas-pixel-9",
- "phone_number": "+43 664 123 45 67",
- "platform": "ANDROID",
- "description": "Jonas Leitner's service device"
}CreatedTechnicianDevice
{- "id": "00000000-0000-4000-8000-000000004001",
- "created_at": "2026-08-20T08:00:00Z",
- "updated_at": "2026-08-20T08:00:00Z",
- "lock_version": 0,
- "natural_id": 17,
- "kind": "TOURFOLD_APP",
- "device_model": "Pixel 9",
- "device_identity_id": "jonas-pixel-9",
- "provisioning_state": "PROVISIONED",
- "phone_number": "+436641234567",
- "platform": "ANDROID",
- "description": "Jonas Leitner's service device"
}Generates a setup payload the client renders as a QR code. The payload is routed by device kind: a rotating Tourfold App enrollment link, the idempotent OsmAnd intake URL, or the tracking-device connection-profile endpoint. Secret-bearing material is only ever returned from this action, never from Device reads.
| device_id required | string <uuid> UUID of the device. |
TechnicianAppSetupCode
{- "device_id": "00000000-0000-4000-8000-000000004001",
- "type": "TOURFOLD_APP_ENROLLMENT",
- "expires_at": "2026-08-20T10:30:00Z"
}Sends a Tourfold App setup link to the device's stored phone number. The link carries a one-time enrollment secret and is delivered only in the SMS — the response never includes the URL or secret. Supported for Tourfold App devices only.
| device_id required | string <uuid> UUID of the device. |
TechnicianSetupSmsScheduled
{- "device_id": "00000000-0000-4000-8000-000000004001",
- "sent_to": "+4369917246437",
- "expires_at": "2026-08-20T10:30:00Z"
}Rotates the device intake secret, invalidating the previous one. Returns no body — the new usable configuration (URL + secret) is obtained via the setup-codes action, keeping a single rendering path and never exposing the secret in a cacheable response.
| device_id required | string <uuid> UUID of the device. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Marks a device as inactive while keeping telemetry history and intake data.
| device_id required | string <uuid> UUID of the device. |
DeactivatedTechnicianDevice
{- "id": "00000000-0000-4000-8000-000000004001",
- "created_at": "2026-08-20T08:00:00Z",
- "updated_at": "2026-08-20T10:00:00Z",
- "lock_version": 2,
- "natural_id": 17,
- "kind": "TOURFOLD_APP",
- "device_model": "Pixel 9",
- "device_identity_id": "jonas-pixel-9",
- "provisioning_state": "DISABLED",
- "phone_number": "+4369917246437",
- "platform": "ANDROID",
- "description": "Jonas Leitner's service device"
}Marks an inactive device as provisioned and usable again.
| device_id required | string <uuid> UUID of the device. |
ActivatedTechnicianDevice
{- "id": "00000000-0000-4000-8000-000000004001",
- "created_at": "2026-08-20T08:00:00Z",
- "updated_at": "2026-08-20T08:00:00Z",
- "lock_version": 0,
- "natural_id": 17,
- "kind": "TOURFOLD_APP",
- "device_model": "Pixel 9",
- "device_identity_id": "jonas-pixel-9",
- "provisioning_state": "PROVISIONED",
- "phone_number": "+436641234567",
- "platform": "ANDROID",
- "description": "Jonas Leitner's service device"
}Returns a device with its latest telemetry snapshot.
| device_id required | string <uuid> UUID of the device. |
| include | Array of strings Items Value: "current_state" Example: include=current_state Optional related resources to embed. Supported: |
TechnicianDevice
{- "id": "00000000-0000-4000-8000-000000004001",
- "created_at": "2026-08-20T08:00:00Z",
- "updated_at": "2026-08-20T08:00:00Z",
- "lock_version": 0,
- "natural_id": 17,
- "kind": "TOURFOLD_APP",
- "device_model": "Pixel 9",
- "device_identity_id": "jonas-pixel-9",
- "provisioning_state": "PROVISIONED",
- "phone_number": "+436641234567",
- "platform": "ANDROID",
- "description": "Jonas Leitner's service device"
}Deletes a device and its telemetry history.
| device_id required | string <uuid> UUID of the device. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}JSON Merge Patch (RFC 7386): omitted fields remain unchanged; a field set to null is cleared (phone_number and description). Provisioning state is system-managed and cannot be changed through this endpoint.
| device_id required | string <uuid> UUID of the device. |
| lock_version | integer or null <int64> Optimistic-locking version: validated when provided (409 on mismatch); omitting it skips the concurrency check |
| kind | string Enum: "TOURFOLD_APP" "THIRD_PARTY_OSMAND" "TRACKING_DEVICE" Device kind. Omitted leaves the value unchanged. Explicit null is rejected (422) — kind is required and cannot be cleared. |
| device_model | string or null Human-readable model or tracker type. Omitted leaves the value unchanged; explicit null clears it. |
| device_identity_id | string or null Stable device identifier. Omitted leaves the value unchanged; explicit null clears it. Once set it cannot be changed to a different value. |
| connection_profile | string or null Provider connection profile selected for tracking hardware, for example OSMAND_HTTP_ONLY. Omitted leaves the value unchanged; explicit null clears it. |
| phone_number | string or null International phone number. An explicit '+' country code is required; common formatting is accepted and normalized to canonical E.164. National numbers are rejected. Omitted leaves the value unchanged; explicit null clears it. |
| platform | string Enum: "UNKNOWN" "IOS" "ANDROID" Mobile platform. Omitted leaves the value unchanged. Explicit null is rejected (422) — platform is required and cannot be cleared. |
| description | string or null Optional operator notes. Omitted leaves the value unchanged; explicit null clears it. |
UpdateTechnicianPhone
{- "lock_version": 0,
- "phone_number": "+43 699 172 464 37"
}UpdatedTechnicianDevice
{- "id": "00000000-0000-4000-8000-000000004001",
- "created_at": "2026-08-20T08:00:00Z",
- "updated_at": "2026-08-20T09:30:00Z",
- "lock_version": 1,
- "natural_id": 17,
- "kind": "TOURFOLD_APP",
- "device_model": "Pixel 9",
- "device_identity_id": "jonas-pixel-9",
- "provisioning_state": "PROVISIONED",
- "phone_number": "+4369917246437",
- "platform": "ANDROID",
- "description": "Jonas Leitner's service device"
}Returns the latest materialized state (status, location, battery, app) for one device.
| device_id required | string <uuid> UUID of the device. |
TechnicianDeviceCurrentState
{- "device_id": "00000000-0000-4000-8000-000000004001",
- "last_seen_at": "2026-08-20T09:29:45Z",
- "status": {
- "connectivity": "ONLINE",
- "updated_at": "2026-08-20T09:29:45Z"
}
}Returns neutral supported device kinds and setup profiles. Provider internals and credentials are not exposed.
SupportedTrackingDevice
{- "items": [
- {
- "kind": "TRACKING_DEVICE",
- "connection_profiles": [
- {
- "id": "OSMAND_HTTP_ONLY",
- "label": "OsmAnd compatible HTTP only",
- "protocol": "OsmAnd HTTP",
- "identity_label": "Device ID",
- "identity_required": true,
- "setup": {
- "server": "device-intake.tourfold.com",
- "port": 5055,
- "protocol": "OsmAnd HTTP"
}, - "compatible_devices": [
- "OsmAnd compatible tracker"
]
}
]
}
]
}Returns the latest materialized state for each requested, tenant-visible device id.
| device_ids | Array of strings <uuid> [ items <uuid > ] Device ids to retrieve (max 100). Repeat the device_ids query parameter for each value. |
TechnicianDeviceCurrentStates
{- "items": [
- {
- "device_id": "00000000-0000-4000-8000-000000004001",
- "last_seen_at": "2026-08-20T09:29:45Z",
- "status": {
- "connectivity": "ONLINE",
- "updated_at": "2026-08-20T09:29:45Z"
}
}
]
}Returns the type's class-level access-control entries (per role/user/everyone). Requires the custom-objects:definitions:read grant plus, per type, the custom-objects:definitions:edit-permissions grant or ownership. Only PROTECTED types have a matrix (records / readOnly types return 422).
| definition_slug required | string Slug of the custom-object definition. |
EquipmentPermissions
{- "definition_slug": "equipment",
- "entries": [
- {
- "principal_type": "everyone",
- "level": "read"
}, - {
- "principal_type": "role",
- "role_name": "technician",
- "level": "write"
}
]
}Stores the supplied entries as the type's complete class-level matrix (a replace, not a merge). Requires the custom-objects:definitions:read grant plus, per type, the custom-objects:definitions:edit-permissions grant or ownership.
| definition_slug required | string Slug of the custom-object definition. |
required | Array of objects (CustomObjectPermissionEntryInput) The complete list of entries the type should have after this call. | ||||||||
Array
| |||||||||
ReplaceEquipmentPermissions
{- "entries": [
- {
- "principal_type": "everyone",
- "level": "read"
}, - {
- "principal_type": "role",
- "role_name": "technician",
- "level": "write"
}
]
}ReplacedEquipmentPermissions
{- "definition_slug": "equipment",
- "entries": [
- {
- "principal_type": "everyone",
- "level": "read"
}, - {
- "principal_type": "role",
- "role_name": "technician",
- "level": "write"
}
]
}When events occur in Tourfold, webhook payloads are sent via HTTP POST to your configured endpoint URLs. Each delivery carries these headers:
v1,<base64> (see below).Deliveries are signed following the Standard Webhooks specification — verify them with an official standardwebhooks library for your language, passing your endpoint's secret (the full whsec_... string) and the three webhook-* headers.
Verifying manually instead: the signature is an HMAC-SHA256 over the string {webhook-id}.{webhook-timestamp}.{raw_body} — the three parts joined with a literal dot, where raw_body is the exact request body bytes as received (do not re-serialize the JSON). The HMAC key is the secret after stripping the whsec_ prefix and base64-decoding the remainder.
key = base64_decode( secret without the "whsec_" prefix )
signed_content = webhook_id + "." + webhook_timestamp + "." + raw_body
expected = "v1," + base64( hmac_sha256( key, utf8_bytes(signed_content) ) )
valid = constant_time_compare(expected, webhook_signature_header)
To protect against replay, also reject deliveries whose webhook-timestamp is outside your tolerance window (5 minutes is a common choice).
The secret is returned exactly once — on endpoint creation and on secret rotation.
Every delivery has the same envelope: type (the event type), id, event_id, timestamp, payload_version, tenant_id, optional actor and request, and data. The resource itself is at data.object, and data.previous_attributes carries the old values of whatever an edit changed.
data.object always identifies the resource, and within one payload_version its fields are only ever added to — never removed, renamed or retyped. Treat the key set as open and ignore keys you do not recognise.
Returns every event type this workspace can subscribe to, as <resource path>.<verb>.
Subscribe to exact names or to patterns: a trailing * after any path prefix (folder.*), a leading * for one verb across all resources (*.created), or * for everything. A wildcard verb widens the path to a prefix; a named verb pins it exactly — so folder.* also matches folder.permissions.updated, while folder.updated does not.
The list is tenant-scoped because it includes one set of event types per custom-object definition, which is the main reason to fetch it at runtime rather than hard-coding it.
EventTypes
{- "items": [
- {
- "type": "folder.updated",
- "resource_path": "folder",
- "verb": "updated"
}, - {
- "type": "folder.permissions.updated",
- "resource_path": "folder.permissions",
- "verb": "updated"
}, - {
- "type": "custom_object.invoice.created",
- "resource_path": "custom_object",
- "verb": "created",
- "definition_slug": "invoice"
}
]
}Manage MCP server settings for the tenant. Controls whether MCP is enabled and which operations are allowed.
Partially updates the MCP server settings. Omit a field to leave it unchanged. Set mode to OFF to disable MCP entirely, READ_ONLY to allow read operations only, or READ_WRITE to allow all operations.
| mode | string Enum: "OFF" "READ_ONLY" "READ_WRITE" New operating mode. Omit to leave unchanged; explicit null is rejected (422). |
EnableReadOnlyMcp
{- "mode": "READ_ONLY"
}UpdatedReadOnlyMcpSettings
{- "mode": "READ_ONLY",
- "tenant_id": "00000000-0000-4000-8000-000000000001"
}Retrieves a custom object instance by ID
| definition_slug required | string Slug of the custom-object definition. |
| instance_id required | string <uuid> UUID of the custom-object instance. |
EquipmentInstance
{- "schema": {
- "slug": "equipment",
- "title": "Equipment",
- "type": "object"
}, - "data": {
- "id": "6f3d2a10-0000-4000-8000-000000000101",
- "created_at": "2026-03-01T08:10:00Z",
- "updated_at": "2026-03-01T08:10:00Z",
- "name": "Rooftop HVAC Unit RTU-17",
- "asset_tag": "AFS-RTU-17",
- "serial_number": "RTU17-2021-0042",
- "category": "hvac",
- "installed_at": "2021-03-14T09:30:00Z",
- "active": true
}, - "display_value": "Rooftop HVAC Unit RTU-17 · AFS-RTU-17",
- "lock_version": 0
}Updates an existing custom object instance
| definition_slug required | string Slug of the custom-object definition. |
| instance_id required | string <uuid> UUID of the custom-object instance. |
required | object Updated instance data as key-value pairs |
| lock_version | integer <int64> Optimistic-locking version: validated when provided (409 on mismatch); omitting it skips the concurrency check |
ReplaceEquipmentInstance
{- "lock_version": 2,
- "data": {
- "name": "Rooftop HVAC Unit RTU-17",
- "asset_tag": "AFS-RTU-17",
- "serial_number": "RTU17-2021-0042",
- "category": "hvac",
- "installed_at": "2021-03-14T09:30:00Z",
- "active": false,
- "specifications": {
- "manufacturer": "Kelvion",
- "model": "RTU 500",
- "power_kw": 55
}, - "supported_services": [
- "inspection",
- "filter_replacement",
- "compressor_service"
]
}
}ReplacedEquipmentInstance
{- "schema": {
- "slug": "equipment",
- "title": "Equipment",
- "type": "object"
}, - "data": {
- "id": "6f3d2a10-0000-4000-8000-000000000101",
- "created_at": "2026-03-01T08:10:00Z",
- "updated_at": "2026-03-03T10:30:00Z",
- "name": "Rooftop HVAC Unit RTU-17",
- "asset_tag": "AFS-RTU-17",
- "serial_number": "RTU17-2021-0042",
- "category": "hvac",
- "installed_at": "2021-03-14T09:30:00Z",
- "active": false
}, - "display_value": "Rooftop HVAC Unit RTU-17 · AFS-RTU-17",
- "lock_version": 3
}Deletes a custom object instance by ID
| definition_slug required | string Slug of the custom-object definition. |
| instance_id required | string <uuid> UUID of the custom-object instance. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Creates one or more instances of one or more custom object definitions, and the associations between them, in a single transaction. Each association references its sides either by *_instance_key (an in-request reference to a key carried by another instances[] item) or by *_instance_id (an existing instance).
required | Array of objects (BatchCreateInstanceItem) Instances to create |
Array of objects (BatchAssociationItem) Associations between the instances and/or existing instances |
BatchCreateEquipment
{- "instances": [
- {
- "definition_slug": "equipment",
- "key": "rtu-17",
- "data": {
- "name": "Rooftop HVAC Unit RTU-17",
- "asset_tag": "AFS-RTU-17",
- "serial_number": "RTU17-2021-0042",
- "category": "hvac",
- "installed_at": "2021-03-14T09:30:00Z",
- "active": true,
- "specifications": {
- "manufacturer": "Kelvion",
- "model": "RTU 500",
- "power_kw": 55
}, - "supported_services": [
- "inspection",
- "filter_replacement"
]
}
}, - {
- "definition_slug": "equipment",
- "key": "lift-01",
- "data": {
- "name": "Passenger Lift LIFT-01",
- "asset_tag": "AFS-LIFT-01",
- "serial_number": "LIFT01-2016-0088",
- "category": "elevator",
- "installed_at": "2016-11-20T07:00:00Z",
- "active": true,
- "specifications": {
- "manufacturer": "Schindler",
- "model": "5500",
- "power_kw": 11
}, - "supported_services": [
- "inspection"
]
}
}
]
}CreatedEquipmentBatch
{- "instances": [
- {
- "key": "rtu-17",
- "definition_slug": "equipment",
- "instance": {
- "schema": {
- "slug": "equipment",
- "title": "Equipment",
- "type": "object"
}, - "data": {
- "id": "6f3d2a10-0000-4000-8000-000000000101",
- "created_at": "2026-03-01T08:10:00Z",
- "updated_at": "2026-03-01T08:10:00Z",
- "name": "Rooftop HVAC Unit RTU-17",
- "asset_tag": "AFS-RTU-17",
- "serial_number": "RTU17-2021-0042",
- "category": "hvac",
- "installed_at": "2021-03-14T09:30:00Z",
- "active": true
}, - "display_value": "Rooftop HVAC Unit RTU-17 · AFS-RTU-17",
- "lock_version": 0
}
}, - {
- "key": "lift-01",
- "definition_slug": "equipment",
- "instance": {
- "schema": {
- "slug": "equipment",
- "title": "Equipment",
- "type": "object"
}, - "data": {
- "id": "6f3d2a10-0000-4000-8000-000000000102",
- "created_at": "2026-03-01T08:10:00Z",
- "updated_at": "2026-03-01T08:10:00Z",
- "name": "Passenger Lift LIFT-01",
- "asset_tag": "AFS-LIFT-01",
- "serial_number": "LIFT01-2016-0088",
- "category": "elevator",
- "installed_at": "2016-11-20T07:00:00Z",
- "active": true
}, - "display_value": "Passenger Lift LIFT-01 · AFS-LIFT-01",
- "lock_version": 0
}
}
]
}Retrieves all instances of a custom object definition
| definition_slug required | string Slug of the custom-object definition. |
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 10 Example: size=10 Number of items per page (max 100). |
EquipmentPage
{- "items": [
- {
- "data": {
- "id": "6f3d2a10-0000-4000-8000-000000000101",
- "created_at": "2026-03-01T08:10:00Z",
- "updated_at": "2026-03-03T10:30:00Z",
- "name": "Rooftop HVAC Unit RTU-17",
- "asset_tag": "AFS-RTU-17",
- "active": false
}, - "display_value": "Rooftop HVAC Unit RTU-17 · AFS-RTU-17",
- "lock_version": 3
}
], - "schema": {
- "slug": "equipment",
- "title": "Equipment",
- "type": "object"
}, - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Retrieves instances associated with a specific instance via a relation
| definition_slug required | string Slug of the custom-object definition. |
| instance_id required | string <uuid> UUID of the custom-object instance. |
| relation_slug required | string Slug of the custom-object relation. |
EquipmentMaintenanceRequests
{- "items": [
- {
- "data": {
- "id": "6f3d2a10-0000-4000-8000-000000000201",
- "created_at": "2026-03-02T08:15:00Z",
- "updated_at": "2026-03-02T08:15:00Z",
- "title": "Temperature too high on third floor",
- "priority": "urgent",
- "resolved": false
}, - "display_value": "Temperature too high on third floor",
- "lock_version": 0
}
], - "schema": {
- "slug": "maintenance_request",
- "title": "Maintenance Request",
- "type": "object"
}, - "page": {
- "size": 1,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
} Delete event tracking for CDC-style incremental sync with delete detection.
This endpoint allows external systems (e.g., Airbyte connectors) to poll for entity deletions
within a time range, enabling downstream systems to remove stale records.
Events are retained for 28 days before automatic cleanup.
Returns a paginated list of delete events within the specified time range.
Use this endpoint for CDC-style incremental sync to detect which entities have been deleted.
Events are sorted by `deleted_at` (ascending) with secondary sort by `id` for deterministic pagination.
**Cursor-based incremental sync:**
- Use `deleted_at` as the cursor field
- On first sync, use a `deleted_from` timestamp in the past and `deleted_to` as current time
- On subsequent syncs, use the last `deleted_at` value from the previous sync as the new `deleted_from`
| deleted_from required | string <date-time> Example: deleted_from=2024-01-01T00:00:00Z Lower bound for |
| deleted_to required | string <date-time> Example: deleted_to=2024-01-02T00:00:00Z Upper bound for |
| entity_type | string Example: entity_type=user Filter by entity type (e.g., user, vehicle, tour). If not specified, returns all entity types. |
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 1000 ] Default: 100 Example: size=100 Number of elements per page (max 1000). The cap is deliberately higher than the platform default of 100 because sync-style consumers replay deletions in bulk. |
DeletedEventsListResponse
{- "items": [
- {
- "id": "a1b2c3d4-e5f6-4a1b-8c9d-123456789abc",
- "entity_type": "user",
- "entity_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
- "deleted_at": "2024-01-01T12:00:00Z"
}, - {
- "id": "b2c3d4e5-f6a1-4b2c-9d8e-234567890bcd",
- "entity_type": "vehicle",
- "entity_id": "550e8400-e29b-41d4-a716-446655440000",
- "deleted_at": "2024-01-01T12:30:00Z"
}
], - "page": {
- "number": 0,
- "size": 100,
- "total_elements": 42,
- "total_pages": 1
}
}Returns the entries stored directly on the folder (one per principal: everyone / role / user), for rendering the permissions editor. For a top-level folder with no entries of its own, the tenant-wide default matrix it effectively resolves to is returned instead, flagged via from_tenant_default. An empty list on a non-root folder means it inherits its parent. Requires the documents:read grant to reach the feature and, per folder, either the documents:edit_permissions grant or ownership — otherwise 403.
| folder_id required | string <uuid> UUID of the folder. |
EquipmentManualPermissions
{- "folder_id": "00000000-0000-4000-8000-000000007001",
- "entries": [
- {
- "principal_type": "role",
- "role_name": "technician",
- "level": "write"
}, - {
- "principal_type": "user",
- "user_id": "00000000-0000-4000-8000-000000001001",
- "user_name": "Mara Berger",
- "level": "write"
}
], - "inherited": false
}Stores the supplied entries as the folder's complete set (a replace, not a merge); an empty list clears them so the folder inherits. everyone may coexist with role/user entries. Requires the documents:read grant plus, per folder, the documents:edit_permissions grant or ownership. Returns the saved entries.
| folder_id required | string <uuid> UUID of the folder. |
required | Array of objects (PermissionEntryInput) The complete list of entries the folder should have after this call. | ||||||||
Array
| |||||||||
ReplaceEquipmentManualPermissions
{- "entries": [
- {
- "principal_type": "role",
- "role_name": "technician",
- "level": "write"
}, - {
- "principal_type": "user",
- "user_id": "00000000-0000-4000-8000-000000001001",
- "level": "write"
}
]
}ReplacedEquipmentManualPermissions
{- "folder_id": "00000000-0000-4000-8000-000000007001",
- "entries": [
- {
- "principal_type": "role",
- "role_name": "technician",
- "level": "write"
}, - {
- "principal_type": "user",
- "user_id": "00000000-0000-4000-8000-000000001001",
- "user_name": "Mara Berger",
- "level": "write"
}
], - "inherited": false
}Returns the entries stored directly on the document (one per principal: everyone / role / user), for rendering the permissions editor. An empty list means the document has no override and inherits its folder. Requires the documents:read grant to reach the feature and, per document, permission-management rights (the document's creator, the owning folder's manager, or the documents:edit_permissions grant) — otherwise 403.
| document_id required | string <uuid> UUID of the document. |
ServiceManualPermissions
{- "document_id": "00000000-0000-4000-8000-000000007101",
- "entries": [
- {
- "principal_type": "user",
- "user_id": "00000000-0000-4000-8000-000000001002",
- "user_name": "Jonas Leitner",
- "level": "write"
}
], - "inherited": false
}Stores the supplied entries as the document's complete override set (a replace, not a merge); an empty list clears the override so the document inherits its folder again. everyone may coexist with role/user entries. Requires the documents:read grant plus, per document, permission-management rights (the document's creator, the owning folder's manager, or the documents:edit_permissions grant). Returns the saved entries.
| document_id required | string <uuid> UUID of the document. |
required | Array of objects (PermissionEntryInput) The complete list of entries the document should have after this call. | ||||||||
Array
| |||||||||
ReplaceServiceManualPermissions
{- "entries": [
- {
- "principal_type": "user",
- "user_id": "00000000-0000-4000-8000-000000001002",
- "level": "write"
}
]
}ReplacedServiceManualPermissions
{- "document_id": "00000000-0000-4000-8000-000000007101",
- "entries": [
- {
- "principal_type": "user",
- "user_id": "00000000-0000-4000-8000-000000001002",
- "user_name": "Jonas Leitner",
- "level": "write"
}
], - "inherited": false
}Returns folders that are direct children of parent_id (or root folders when parent_id is omitted), paginated in ascending name order. Default page size is 20, capped at 100. Folders of kind = managed_branch whose namespace is owned by a registered managed-folder provider are auto-expanded: the response surfaces one folder per managed subject at this depth, lazy-creating any missing rows. The provider's order is authoritative for managed pages. Requires the documents:read grant.
| parent_id | string <uuid> Parent folder id; omit for root listing. |
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
AlpineRootFolders
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000008001",
- "lock_version": 0,
- "name": "Equipment manuals",
- "display_name": "Equipment manuals",
- "kind": "user",
- "created_at": "2026-08-20T08:15:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Creates a folder under the given parent (or at the root if no parent is supplied). Requires the documents:create grant.
| name required | string Display name of the folder. Validated server-side: NFC-normalized, max 255 codepoints, no path separators / control chars / Windows-reserved characters, not a reserved name. |
| parent_id | string <uuid> Parent folder id. Omit for a top-level folder. |
CreateEquipmentManualsFolder
{- "name": "Equipment manuals"
}CreatedEquipmentManualsFolder
{- "id": "00000000-0000-4000-8000-000000008001",
- "lock_version": 0,
- "name": "Equipment manuals",
- "display_name": "Equipment manuals",
- "kind": "user",
- "created_at": "2026-08-20T08:15:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Idempotent: re-starring a folder is a no-op and returns the same detail response with starred=true. Requires the documents:update grant.
| folder_id required | string <uuid> UUID of the folder. |
StarredEquipmentManualsFolder
{- "id": "00000000-0000-4000-8000-000000008001",
- "lock_version": 0,
- "name": "Equipment manuals",
- "display_name": "Equipment manuals",
- "kind": "user",
- "created_at": "2026-08-20T08:15:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "starred": true,
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Idempotent: un-starring a folder that was not starred is a no-op. Returns the folder detail with starred=false. Requires the documents:update grant.
| folder_id required | string <uuid> UUID of the folder. |
UnstarredEquipmentManualsFolder
{- "id": "00000000-0000-4000-8000-000000008001",
- "lock_version": 0,
- "name": "Equipment manuals",
- "display_name": "Equipment manuals",
- "kind": "user",
- "created_at": "2026-08-20T08:15:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "starred": false,
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Asynchronously extracts structured fields from the version. The call returns immediately with a document-management extraction id. Clients should listen for events.documents SSE lifecycle events and may poll GET /documents/extractions/{extraction_id} as a fallback until the status reaches a terminal state. Each call appends a new extraction (re-analysis is supported by submitting again). Terminal payloads are copied into document-management before the analyzer job is acked. Requires the documents:update grant.
| document_id required | string <uuid> UUID of the document. |
| version_id required | string <uuid> UUID of the document version. |
Rtu17AnalysisAccepted
{- "extraction_id": "00000000-0000-4000-8000-000000008005",
- "status": "pending"
}Creates a new draft [DocumentVersion] with version_number = max + 1, returns a presigned upload form. The current version pointer does NOT change until POST /documents/{document_id}/finalize is called. Requires the documents:update grant.
| document_id required | string <uuid> UUID of the document. |
| mime_type required | string non-empty MIME type of the file being uploaded. Must equal the document's current MIME type — uploading a different content type creates a different document, not a new version. Mismatches are rejected with |
| original_file_name | string Filename of the file being uploaded (e.g. |
| change_note | string Optional free-form note describing what's new in this version. Stored on the version row. |
UploadRtu17ManualRevision
{- "mime_type": "application/pdf",
- "original_file_name": "RTU-17-service-manual-rev-2.pdf",
- "change_note": "Added the revised filter replacement schedule."
}Rtu17ManualRevisionUploadIntent
{- "document_id": "00000000-0000-4000-8000-000000008002",
- "version_id": "00000000-0000-4000-8000-000000008004",
- "upload": {
- "form_fields": {
- "key": "documents/00000000-0000-4000-8000-000000008002/v2",
- "content-type": "application/pdf"
}, - "expires_at": "2026-08-20T09:45:00Z",
- "storage_key": "documents/00000000-0000-4000-8000-000000008002/v2"
}
}Idempotent: re-starring a document is a no-op and returns the same detail response with starred=true. Requires the documents:update grant.
| document_id required | string <uuid> UUID of the document. |
StarredRtu17ServiceManual
{- "id": "00000000-0000-4000-8000-000000008002",
- "lock_version": 1,
- "folder_id": "00000000-0000-4000-8000-000000008001",
- "name": "RTU-17 service manual.pdf",
- "description": "Manufacturer service manual for rooftop unit RTU-17.",
- "current_version_id": "00000000-0000-4000-8000-000000008004",
- "size": 248320,
- "mime_type": "application/pdf",
- "created_at": "2026-08-20T08:30:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "starred": true,
- "preview_available": true,
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Idempotent: un-starring a document that was not starred is a no-op. Returns the document detail with starred=false. Requires the documents:update grant.
| document_id required | string <uuid> UUID of the document. |
UnstarredRtu17ServiceManual
{- "id": "00000000-0000-4000-8000-000000008002",
- "lock_version": 1,
- "folder_id": "00000000-0000-4000-8000-000000008001",
- "name": "RTU-17 service manual.pdf",
- "description": "Manufacturer service manual for rooftop unit RTU-17.",
- "current_version_id": "00000000-0000-4000-8000-000000008004",
- "size": 248320,
- "mime_type": "application/pdf",
- "created_at": "2026-08-20T08:30:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "starred": false,
- "preview_available": true,
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Soft-deletes the document — the row is moved to the user's Trash and can be restored later. The captured original_path text is recorded so the restore flow can put the document back where it came from. Idempotent. Hard-delete (permanent removal) is DELETE /documents/{document_id} and is only allowed on rows that have already been soft-deleted. Requires the documents:delete grant.
| document_id required | string <uuid> UUID of the document. |
TrashedRtu17ServiceManual
{- "id": "00000000-0000-4000-8000-000000008002",
- "lock_version": 2,
- "name": "RTU-17 service manual.pdf",
- "description": "Manufacturer service manual for rooftop unit RTU-17.",
- "current_version_id": "00000000-0000-4000-8000-000000008004",
- "size": 248320,
- "mime_type": "application/pdf",
- "created_at": "2026-08-20T08:30:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "soft_deleted_at": "2026-08-20T10:00:00Z",
- "soft_deleted_by": "00000000-0000-4000-8000-000000000102",
- "original_path": "/Equipment manuals/",
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Restores a soft-deleted document from the Trash. The optional request body lets the caller pick the destination and the conflict-resolution strategy. Target folder: when target_folder_id is supplied, the document is restored into that folder (must exist and be user or managed). When omitted, the captured original_path is walked through the live tree and any missing folders are auto-created as user folders so the document reappears at its original location. Conflict resolution (when a live sibling already has the same name): rename uses the supplied new_name for the restored document; new_version appends the restored document's current version as a new version of the existing live sibling and hard-deletes the soft-deleted row (the MIME types must match — otherwise 422 version-mime-mismatch). When conflict_resolution is omitted and a name collision exists, the call rejects with 409 name-taken. Requires the documents:update grant.
| document_id required | string <uuid> UUID of the document. |
| target_folder_id | string <uuid> Folder to restore into. Omit to use the document's captured |
| conflict_resolution | string Enum: "rename" "new_version" How to handle a name collision in the target folder. Allowed: |
| new_name | string Replacement name. Required when |
RestoreToEquipmentManuals
{- "target_folder_id": "00000000-0000-4000-8000-000000008001"
}RestoredRtu17ServiceManual
{- "id": "00000000-0000-4000-8000-000000008002",
- "lock_version": 1,
- "folder_id": "00000000-0000-4000-8000-000000008001",
- "name": "RTU-17 service manual.pdf",
- "description": "Manufacturer service manual for rooftop unit RTU-17.",
- "current_version_id": "00000000-0000-4000-8000-000000008004",
- "size": 248320,
- "mime_type": "application/pdf",
- "created_at": "2026-08-20T08:30:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Completes the latest pending upload for the given document, populates the version's size and MIME type from the filestore rendition, and points current_version_id at it. Idempotent only when called more than once for the same upload — for replacing an existing version, use POST /documents/{document_id}/versions/initiate-upload (slice 3b-ii). Requires the documents:create grant.
| document_id required | string <uuid> UUID of the document. |
FinalizedRtu17ServiceManual
{- "id": "00000000-0000-4000-8000-000000008002",
- "lock_version": 1,
- "folder_id": "00000000-0000-4000-8000-000000008001",
- "name": "RTU-17 service manual.pdf",
- "description": "Manufacturer service manual for rooftop unit RTU-17.",
- "current_version_id": "00000000-0000-4000-8000-000000008004",
- "size": 248320,
- "mime_type": "application/pdf",
- "created_at": "2026-08-20T08:30:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Creates a draft document and a draft version, then returns a presigned upload form. The client POSTs the binary content to the form URL, then calls POST /documents/{document_id}/finalize to complete the upload. Until finalize succeeds, the document's current_version_id is null. Requires the documents:create grant.
| name required | string Display name of the document. Validated server-side: NFC-normalized, max 255 codepoints, no path separators / control chars / Windows-reserved characters, not a reserved name. |
| folder_id required | string <uuid> Folder this document will live in. |
| mime_type required | string MIME type of the file being uploaded. |
UploadRtu17ServiceManual
{- "name": "RTU-17 service manual.pdf",
- "folder_id": "00000000-0000-4000-8000-000000008001",
- "mime_type": "application/pdf"
}Rtu17ManualUploadIntent
{- "document_id": "00000000-0000-4000-8000-000000008002",
- "version_id": "00000000-0000-4000-8000-000000008003",
- "upload": {
- "form_fields": {
- "key": "documents/00000000-0000-4000-8000-000000008002/v1",
- "content-type": "application/pdf"
}, - "expires_at": "2026-08-20T08:45:00Z",
- "storage_key": "documents/00000000-0000-4000-8000-000000008002/v1"
}
}Returns the active document-management settings for the calling tenant. Currently the only setting is auto_hard_delete_after_days, which drives the daily auto-hard-delete cron. Requires the documents:read grant.
AlpineDocumentRetention
{- "auto_hard_delete_after_days": 45
}JSON merge patch semantics: a field present in the body is applied; an absent field is left unchanged. auto_hard_delete_after_days must be an integer in the inclusive range 1..180. Out-of-range values produce 422 with document-management/invalid-retention-days. Requires the documents:settings:update grant.
| auto_hard_delete_after_days | integer <int32> [ 1 .. 180 ] Number of days after which a soft-deleted document is permanently removed. Must be in the inclusive range 1..180. Field omitted leaves the value unchanged; explicit null is rejected (the field is required and cannot be cleared). |
SetDocumentRetention
{- "auto_hard_delete_after_days": 45
}UpdatedAlpineDocumentRetention
{- "auto_hard_delete_after_days": 45
}Returns the folder with the given id. Requires the documents:read grant.
| folder_id required | string <uuid> UUID of the folder. |
EquipmentManualsFolder
{- "id": "00000000-0000-4000-8000-000000008001",
- "lock_version": 0,
- "name": "Equipment manuals",
- "display_name": "Equipment manuals",
- "kind": "user",
- "created_at": "2026-08-20T08:15:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "starred": true,
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Hard-deletes the folder and any subfolders. Every contained document is soft-deleted as part of the same operation — its original_path (the human-readable folder path text it lived at) is captured so the user can restore it individually later from the Trash. Folders themselves are NEVER soft-deleted: they are simply removed from the live tree. Managed (managed/managed_branch) folders cannot be deleted directly. Requires the documents:delete grant.
| folder_id required | string <uuid> UUID of the folder. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}JSON merge patch semantics: a field present in the body is applied; an absent field is left unchanged. To move a folder under a new parent, send parent_id as a UUID. To move it to the root, send parent_id: null explicitly. Cycles (moving into self or a descendant) are rejected; descendant paths are rebuilt in the same transaction. Requires the documents:update grant.
| folder_id required | string <uuid> UUID of the folder. |
| lock_version | integer or null <int64> Optimistic-locking version: validated when provided (409 on mismatch); omitting it skips the concurrency check |
| name | string New folder name. Validation rules: trimmed, NFC-normalized, 1..255 codepoints, no slashes/backslashes/control characters, not a Windows reserved name. Omitted leaves the value unchanged; explicit null is rejected (422) — name is required and cannot be cleared. |
| parent_id | string or null <uuid> New parent folder id, or null to move to root. Omit to leave the parent unchanged. Cannot move into the folder itself or any of its descendants. Cannot move a managed folder. |
| tag_ids | Array of strings or null <uuid> unique [ items <uuid > ] Replacement set of tag ids. Field omitted leaves tags unchanged; |
RenameAndTagFolder
{- "lock_version": 0,
- "name": "Equipment manuals",
- "tag_ids": [
- "00000000-0000-4000-8000-000000005001"
]
}UpdatedEquipmentManualsFolder
{- "id": "00000000-0000-4000-8000-000000008001",
- "lock_version": 0,
- "name": "Equipment manuals",
- "display_name": "Equipment manuals",
- "kind": "user",
- "created_at": "2026-08-20T08:15:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Returns the document with the given id (soft-deleted documents are returned with soft_deleted_at set). Requires the documents:read grant.
| document_id required | string <uuid> UUID of the document. |
Rtu17ServiceManualDetail
{- "id": "00000000-0000-4000-8000-000000008002",
- "lock_version": 1,
- "folder_id": "00000000-0000-4000-8000-000000008001",
- "name": "RTU-17 service manual.pdf",
- "description": "Manufacturer service manual for rooftop unit RTU-17.",
- "current_version_id": "00000000-0000-4000-8000-000000008004",
- "size": 248320,
- "mime_type": "application/pdf",
- "created_at": "2026-08-20T08:30:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "starred": true,
- "preview_available": true,
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Hard-deletes a soft-deleted document and all its versions. Cannot be called on a live row — soft-delete it first via POST /documents/{document_id}/soft-delete. Filestore blob cleanup is wired up in a later slice. Requires the documents:delete grant.
| document_id required | string <uuid> UUID of the document. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}JSON merge patch semantics: a field present in the body is applied; an absent field is left unchanged. Send description: null explicitly to clear the description. Send folder_id to move the document into another folder atomically — the target must be live and have kind = user or kind = managed (managed leaf); managed_branch is rejected. Name collision is checked against the target folder's siblings when a move is requested. Requires the documents:update grant.
| document_id required | string <uuid> UUID of the document. |
| lock_version | integer or null <int64> Optimistic-locking version: validated when provided (409 on mismatch); omitting it skips the concurrency check |
| name | string New document name. Validation rules match folder names (1..255 codepoints, no slashes/backslashes/control characters, not a Windows reserved name). Omitted leaves the value unchanged; explicit null is rejected (422) — name is required and cannot be cleared. |
| description | string or null Free-form description. Send null to clear; omit to leave unchanged. |
| folder_id | string <uuid> Move the document into the folder with this id. Target must be live and have |
| tag_ids | Array of strings or null <uuid> unique [ items <uuid > ] Replacement set of tag ids. Field omitted leaves tags unchanged; |
DescribeAndTagRtu17Manual
{- "lock_version": 0,
- "description": "Manufacturer service manual for rooftop unit RTU-17.",
- "tag_ids": [
- "00000000-0000-4000-8000-000000005001"
]
}UpdatedRtu17ServiceManual
{- "id": "00000000-0000-4000-8000-000000008002",
- "lock_version": 1,
- "folder_id": "00000000-0000-4000-8000-000000008001",
- "name": "RTU-17 service manual.pdf",
- "description": "Manufacturer service manual for rooftop unit RTU-17.",
- "current_version_id": "00000000-0000-4000-8000-000000008004",
- "size": 248320,
- "mime_type": "application/pdf",
- "created_at": "2026-08-20T08:30:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Returns a lightweight usage snapshot for the calling tenant: live and soft-deleted document counts. Available even when the document-management feature flag is off; used by the gated-tenant upgrade page. Usage and quotas live under the generic usage endpoints. Requires the documents:read grant.
AlpineDocumentUsage
{- "document_count": 24,
- "soft_deleted_document_count": 2
}Returns a single mixed list sorted by starred_at desc, paginated. Each entry's kind field is "folder" or "document"; the corresponding folder or document field is populated. Soft-deleted items are excluded — see GET /soft-deleted for the user's Trash listing. Default page size is 20, capped at 100. Requires the documents:read grant.
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
AlpineStarredDocuments
{- "items": [
- {
- "kind": "document",
- "document": {
- "id": "00000000-0000-4000-8000-000000008002",
- "lock_version": 1,
- "folder_id": "00000000-0000-4000-8000-000000008001",
- "name": "RTU-17 service manual.pdf",
- "created_at": "2026-08-20T08:30:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "access_level": "manage",
- "tags": [ ]
}, - "starred_at": "2026-08-20T09:45:00Z"
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Returns soft-deleted documents (the user's Trash) sorted by soft_deleted_at desc, paginated. Each entry's kind field is always "document" (folders are never soft-deleted in the new model). The corresponding document field is populated and includes the captured original_path text. Default page size is 20, capped at 100. Tenant-wide and gated by the grant only: a soft-deleted document has no live folder (its folder_id is severed on delete), so per-folder ACL filtering cannot apply here. Requires the documents:read grant.
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
AlpineDocumentTrash
{- "items": [
- {
- "kind": "document",
- "document": {
- "id": "00000000-0000-4000-8000-000000008002",
- "lock_version": 2,
- "name": "RTU-17 service manual.pdf",
- "created_at": "2026-08-20T08:30:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "soft_deleted_at": "2026-08-20T10:00:00Z",
- "soft_deleted_by": "00000000-0000-4000-8000-000000000102",
- "original_path": "/Equipment manuals/",
- "access_level": "manage",
- "tags": [ ]
}, - "soft_deleted_at": "2026-08-20T10:00:00Z"
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Walks the tree from the root, matching slash-separated name segments (NFC and case-insensitive). Returns 404 if any segment doesn't match a folder. Requires the documents:read grant.
| path required | string Slash-separated display path, e.g. |
EquipmentManualsFolderByPath
{- "id": "00000000-0000-4000-8000-000000008001",
- "lock_version": 0,
- "name": "Equipment manuals",
- "display_name": "Equipment manuals",
- "kind": "user",
- "created_at": "2026-08-20T08:15:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "starred": true,
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}Returns documents directly in the given folder (not the subtree), paginated. Soft-deleted documents are never returned here — they live under the dedicated /soft-deleted endpoint. Sortable fields: name, createdAt, updatedAt, size. Default sort is name:asc; default page size is 20, capped at 100. Requires the documents:read grant.
| folder_id required | string <uuid> Folder id. |
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
| sort | Array of strings Example: sort=updated_at:desc Repeated sorting criteria in |
EquipmentManualDocuments
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000008002",
- "lock_version": 1,
- "folder_id": "00000000-0000-4000-8000-000000008001",
- "name": "RTU-17 service manual.pdf",
- "description": "Manufacturer service manual for rooftop unit RTU-17.",
- "current_version_id": "00000000-0000-4000-8000-000000008004",
- "size": 248320,
- "mime_type": "application/pdf",
- "created_at": "2026-08-20T08:30:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Returns every version, newest first. Pending (not-yet-finalized) versions have finalized_at = null. Requires the documents:read grant.
| document_id required | string <uuid> UUID of the document. |
Rtu17ManualVersions
[- {
- "id": "00000000-0000-4000-8000-000000008004",
- "document_id": "00000000-0000-4000-8000-000000008002",
- "version_number": 2,
- "size": 248320,
- "mime_type": "application/pdf",
- "uploaded_by": "00000000-0000-4000-8000-000000000102",
- "uploaded_by_name": "Jonas Leitner",
- "uploaded_at": "2026-08-20T09:30:00Z",
- "finalized_at": "2026-08-20T09:31:00Z",
- "original_file_name": "RTU-17-service-manual-rev-2.pdf",
- "change_note": "Added the revised filter replacement schedule.",
- "preview_available": true
}
]Returns up to 50 extractions for the version, newest first. Requires the documents:read grant.
| document_id required | string <uuid> UUID of the document. |
| version_id required | string <uuid> UUID of the document version. |
Rtu17ExtractionHistory
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000008005",
- "document_id": "00000000-0000-4000-8000-000000008002",
- "version_id": "00000000-0000-4000-8000-000000008004",
- "status": "succeeded",
- "created_at": "2026-08-20T09:35:00Z",
- "started_at": "2026-08-20T09:35:02Z",
- "finished_at": "2026-08-20T09:35:08Z",
- "schema": {
- "type": "object",
- "properties": {
- "model": {
- "type": "string"
}, - "filter_replacement_days": {
- "type": "integer"
}
}
}, - "schema_inferred": true,
- "extracted_fields": {
- "model": "RTU-17",
- "filter_replacement_days": 90
}
}
]
}Convenience endpoint: returns the latest extraction whose status is succeeded. Returns 404 (slug extraction-not-found) when no extraction has succeeded yet for this version. Requires the documents:read grant.
| document_id required | string <uuid> UUID of the document. |
| version_id required | string <uuid> UUID of the document version. |
LatestRtu17Extraction
{- "id": "00000000-0000-4000-8000-000000008005",
- "document_id": "00000000-0000-4000-8000-000000008002",
- "version_id": "00000000-0000-4000-8000-000000008004",
- "status": "succeeded",
- "created_at": "2026-08-20T09:35:00Z",
- "started_at": "2026-08-20T09:35:02Z",
- "finished_at": "2026-08-20T09:35:08Z",
- "schema": {
- "type": "object",
- "properties": {
- "model": {
- "type": "string"
}, - "filter_replacement_days": {
- "type": "integer"
}
}
}, - "schema_inferred": true,
- "extracted_fields": {
- "model": "RTU-17",
- "filter_replacement_days": 90
}
}Returns a short-lived presigned URL the client can GET to download the binary content. The URL is signed by the storage backend and expires after a few minutes. The optional rendition query parameter selects which filestore rendition to serve: original (default, the bytes the user uploaded) or preview (a JPEG inline preview, only available for image/PDF uploads when preview_available is true on the version). Requires the documents:read grant.
| document_id required | string <uuid> UUID of the document. |
| version_id required | string <uuid> UUID of the document version. |
| rendition | string Default: "original" Enum: "original" "preview" Rendition alias to serve. Defaults to |
Rtu17ManualDownload
{- "expires_at": "2026-08-20T10:05:00Z"
}Returns finalized, live documents sorted by their current version's uploaded_at descending. With folder_id the result is scoped to that folder's subtree (folder + descendants); without folder_id the listing is tenant-wide. Requires the documents:read grant.
| folder_id | string <uuid> Optional folder scope; when supplied, results are limited to the folder's subtree. |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of rows to return. |
| uploaded_after | string <date-time> Strict RFC 3339 cutoff for the current version's |
RecentEquipmentDocuments
[- {
- "id": "00000000-0000-4000-8000-000000008002",
- "lock_version": 1,
- "folder_id": "00000000-0000-4000-8000-000000008001",
- "name": "RTU-17 service manual.pdf",
- "description": "Manufacturer service manual for rooftop unit RTU-17.",
- "current_version_id": "00000000-0000-4000-8000-000000008004",
- "size": 248320,
- "mime_type": "application/pdf",
- "created_at": "2026-08-20T08:30:00Z",
- "created_by": "00000000-0000-4000-8000-000000000102",
- "created_by_name": "Jonas Leitner",
- "access_level": "manage",
- "tags": [
- {
- "id": "00000000-0000-4000-8000-000000005001",
- "name": "urgent",
- "color": "#D92D20"
}
]
}
]Returns the current durable document-management extraction state. Clients use this for an initial load, SSE-triggered refreshes, and polling fallback while an extraction is still running. Requires the documents:read grant.
| extraction_id required | string <uuid> UUID of the document extraction. |
Rtu17Extraction
{- "id": "00000000-0000-4000-8000-000000008005",
- "document_id": "00000000-0000-4000-8000-000000008002",
- "version_id": "00000000-0000-4000-8000-000000008004",
- "status": "succeeded",
- "created_at": "2026-08-20T09:35:00Z",
- "started_at": "2026-08-20T09:35:02Z",
- "finished_at": "2026-08-20T09:35:08Z",
- "schema": {
- "type": "object",
- "properties": {
- "model": {
- "type": "string"
}, - "filter_replacement_days": {
- "type": "integer"
}
}
}, - "schema_inferred": true,
- "extracted_fields": {
- "model": "RTU-17",
- "filter_replacement_days": 90
}
}Retrieve audit logs with optional filters for time range, scope (USER or TENANT), event type (USER_CREATED or TENANT_CREATED), and actor. Requires 'audit-logs:read' grant.
| occurred_from | string <date-time> Example: occurred_from=2024-01-01T00:00:00Z Lower bound for event occurrence time (inclusive, RFC 3339). Defaults to 1 day ago. |
| occurred_to | string <date-time> Example: occurred_to=2024-12-31T23:59:59Z Upper bound for event occurrence time (exclusive, RFC 3339). Defaults to now. |
| scope_type | string Enum: "USER" "TENANT" Example: scope_type=USER Filter by scope type (USER or TENANT only) |
| scope_id | string Example: scope_id=00000000-0000-4000-8000-000000001002 Filter by the ID of the affected entity (e.g., specific user ID, tour ID, case ID) |
| event_type | string Enum: "USER_CREATED" "TENANT_CREATED" Example: event_type=USER_CREATED Filter by event type |
| actor_id | string Example: actor_id=00000000-0000-4000-8000-000000001001 Filter by the ID of the actor who performed the action |
| page | integer >= 0 Default: 0 Page number (0-based). First page is 0. |
| size | integer [ 1 .. 1000 ] Default: 50 Example: size=50 Number of items per page. Maximum allowed is 1000. |
| sort | Array of strings Example: sort=scope_type:asc Repeated sorting criteria in |
AuditLogsResponse
{- "items": [
- {
- "id": "f8c1b4b5-ffe8-4d1c-8f0a-8c55e7b9c6d1",
- "original_event_time": "2026-08-20T08:05:00Z",
- "scope_type": "USER",
- "scope_id": "00000000-0000-4000-8000-000000001002",
- "event_type": "USER_CREATED",
- "description": "Mara Berger created Jonas Leitner",
- "data": {
- "actor_email": "mara.berger@example.invalid"
}, - "actor_id": "00000000-0000-4000-8000-000000001001",
- "origin": "APPLICATION"
}, - {
- "id": "a83f3f6c-6d3b-4f3a-89d7-1d3c9d0f1c2b",
- "original_event_time": "2026-08-20T08:10:00Z",
- "scope_type": "TENANT",
- "scope_id": "00000000-0000-4000-8000-000000000101",
- "event_type": "TENANT_CREATED",
- "description": "Alpine workspace activated the Scale plan",
- "data": {
- "plan": "scale",
- "actor": "system"
}, - "origin": "APPLICATION"
}
], - "page": {
- "size": 50,
- "total_elements": 2,
- "total_pages": 1,
- "number": 0
}
}Returns a paginated list of areas. Requires the 'areas:read' grant.
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
ServiceAreasPage
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000002001",
- "name": "Vienna North",
- "description": "Alpine Facility Services coverage north of the Danube",
- "color": "#1570EF",
- "geo_json": {
- "type": "Polygon",
- "coordinates": [
- [
- [
- 16.35,
- 48.24
], - [
- 16.48,
- 48.24
], - [
- 16.48,
- 48.32
], - [
- 16.35,
- 48.32
], - [
- 16.35,
- 48.24
]
]
]
}, - "zip_ranges": [
- {
- "country": "AUT",
- "from": "1210",
- "to": "1220"
}
], - "created_at": "2026-08-20T08:30:00Z",
- "updated_at": "2026-08-20T08:30:00Z",
- "lock_version": 0
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Requires the 'areas:create' grant.
| name required | string Display name of the area |
| description | string Optional description |
| color | string Hex color used to render the area overlay on maps |
| geo_json required | any GeoJSON Feature / FeatureCollection containing exactly one Polygon or MultiPolygon |
Array of objects (ZipRange) Optional postal-code ranges that fall inside this area |
CreateViennaNorthArea
{- "name": "Vienna North",
- "description": "Alpine Facility Services coverage north of the Danube",
- "color": "#1570EF",
- "geo_json": {
- "type": "Polygon",
- "coordinates": [
- [
- [
- 16.35,
- 48.24
], - [
- 16.48,
- 48.24
], - [
- 16.48,
- 48.32
], - [
- 16.35,
- 48.32
], - [
- 16.35,
- 48.24
]
]
]
}, - "zip_ranges": [
- {
- "country": "AUT",
- "from": "1210",
- "to": "1220"
}
]
}CreatedViennaNorthArea
{- "id": "00000000-0000-4000-8000-000000002001",
- "name": "Vienna North",
- "description": "Alpine Facility Services coverage north of the Danube",
- "color": "#1570EF",
- "geo_json": {
- "type": "Polygon",
- "coordinates": [
- [
- [
- 16.35,
- 48.24
], - [
- 16.48,
- 48.24
], - [
- 16.48,
- 48.32
], - [
- 16.35,
- 48.32
], - [
- 16.35,
- 48.24
]
]
]
}, - "zip_ranges": [
- {
- "country": "AUT",
- "from": "1210",
- "to": "1220"
}
], - "created_at": "2026-08-20T08:30:00Z",
- "updated_at": "2026-08-20T08:30:00Z",
- "lock_version": 0
}Requires the 'areas:read' grant.
| area_id required | string <uuid> UUID of the area. |
ViennaNorthArea
{- "id": "00000000-0000-4000-8000-000000002001",
- "name": "Vienna North",
- "description": "Alpine Facility Services coverage north of the Danube",
- "color": "#1570EF",
- "geo_json": {
- "type": "Polygon",
- "coordinates": [
- [
- [
- 16.35,
- 48.24
], - [
- 16.48,
- 48.24
], - [
- 16.48,
- 48.32
], - [
- 16.35,
- 48.32
], - [
- 16.35,
- 48.24
]
]
]
}, - "zip_ranges": [
- {
- "country": "AUT",
- "from": "1210",
- "to": "1220"
}
], - "created_at": "2026-08-20T08:30:00Z",
- "updated_at": "2026-08-20T08:30:00Z",
- "lock_version": 0
}Requires the 'areas:delete' grant.
| area_id required | string <uuid> UUID of the area. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}JSON Merge Patch (RFC 7386): omitted fields remain unchanged; a field set to null is cleared (description and color). Requires the 'areas:update' grant.
| area_id required | string <uuid> UUID of the area. |
| name | string Display name of the area. Omitted leaves the value unchanged. Explicit null is rejected (422) — name is required and cannot be cleared. |
| description | string or null Optional description. Omitted leaves the value unchanged; explicit null clears it. |
| color | string or null Hex color used to render the area overlay on maps. Omitted leaves the value unchanged; explicit null clears it. |
| geo_json | any GeoJSON Feature / FeatureCollection containing exactly one Polygon or MultiPolygon. Omitted or null leaves the value unchanged. |
Array of objects or null (ZipRange) Optional postal-code ranges that fall inside this area. Omitted or null leaves the value unchanged; a provided list replaces the stored ranges. | |
| lock_version | integer or null <int64> Optimistic lock version returned by the previous read |
RenameViennaNorthArea
{- "name": "Vienna North Operations",
- "lock_version": 0
}UpdatedViennaNorthArea
{- "id": "00000000-0000-4000-8000-000000002001",
- "name": "Vienna North Operations",
- "description": "Alpine Facility Services coverage north of the Danube",
- "color": "#1570EF",
- "geo_json": {
- "type": "Polygon",
- "coordinates": [
- [
- [
- 16.35,
- 48.24
], - [
- 16.48,
- 48.24
], - [
- 16.48,
- 48.32
], - [
- 16.35,
- 48.32
], - [
- 16.35,
- 48.24
]
]
]
}, - "zip_ranges": [
- {
- "country": "AUT",
- "from": "1210",
- "to": "1220"
}
], - "created_at": "2026-08-20T08:30:00Z",
- "updated_at": "2026-08-20T09:30:00Z",
- "lock_version": 1
}Returns a paginated list of brands.
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Number of items per page (max 100). |
| sort | Array of strings Example: sort=name:asc Repeated sorting criteria in |
| search | string Search term for brand name, email, or phone number. |
BrandsListResponse
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000000801",
- "created_at": "2026-08-20T08:10:00Z",
- "updated_at": "2026-08-20T08:10:00Z",
- "lock_version": 0,
- "name": "Alpine Facility Services GmbH",
- "email": "dispatch@example.invalid",
- "phone_number": "+43123456789",
- "linked_custom_domains": [ ]
}
], - "page": {
- "size": 20,
- "total_elements": 1,
- "total_pages": 1,
- "number": 0
}
}Creates a brand. Logo updates should use the presigned upload intent endpoints under /api/v2/brands/{brand_id}/logo/uploads.
| name required | string [ 0 .. 255 ] characters Brand name |
string <email> [ 0 .. 255 ] characters Brand contact email | |
| phone_number | string [ 0 .. 255 ] characters International contact number. An explicit '+' country code is required; common formatting is accepted and normalized to canonical E.164. National numbers are rejected. |
| theme_id | string <uuid> Optional custom theme linked to this brand |
CreateBrandRequest
{- "name": "Alpine Facility Services GmbH",
- "email": "dispatch@example.invalid",
- "phone_number": "+43 1 234 56 789"
}CreateBrandResponse
{- "id": "00000000-0000-4000-8000-000000000801",
- "created_at": "2026-08-20T08:10:00Z",
- "updated_at": "2026-08-20T08:10:00Z",
- "lock_version": 0,
- "name": "Alpine Facility Services GmbH",
- "email": "dispatch@example.invalid",
- "phone_number": "+43123456789",
- "linked_custom_domains": [ ]
}Creates a presigned upload URL for brand logo uploads (PNG/JPEG only).
| brand_id required | string <uuid> UUID of the brand. |
| original_file_name required | string non-empty Original filename for the brand logo upload. |
| mime_type required | string non-empty (?i)^image/(png|jpe?g)$ MIME type of the brand logo upload (image/png or image/jpeg). |
CreateBrandLogoUpload
{- "original_file_name": "alpine-brand-logo.png",
- "mime_type": "image/png"
}AlpineBrandLogoUpload
{- "file_id": "00000000-0000-4000-8000-000000000811",
- "upload_fields": {
- "key": "alpine/brand-logo.png",
- "policy": "example-not-a-real-policy"
}, - "upload_url_expires_at": "2026-08-20T10:20:00Z"
}Creates a presigned upload URL for brand favicon uploads (PNG only).
| brand_id required | string <uuid> UUID of the brand. |
| original_file_name required | string non-empty Original filename for the brand favicon upload. |
| mime_type required | string non-empty (?i)^image/png$ MIME type of the brand favicon upload (image/png only). |
CreateBrandFaviconUpload
{- "original_file_name": "alpine-brand-favicon.png",
- "mime_type": "image/png"
}AlpineBrandFaviconUpload
{- "file_id": "00000000-0000-4000-8000-000000000812",
- "upload_fields": {
- "key": "alpine/brand-favicon.png",
- "policy": "example-not-a-real-policy"
}, - "upload_url_expires_at": "2026-08-20T10:20:00Z"
}Idempotent: re-linking the same pair is a no-op. Returns 422 if the domain is not in VERIFIED status, or if it is already linked to a different brand.
| brand_id required | string <uuid> UUID of the brand. |
| custom_domain_id required | string <uuid> UUID of the custom-domain link. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Idempotent: unlinking a pair that is not linked returns 204. The custom domain row itself is untouched.
| brand_id required | string <uuid> UUID of the brand. |
| custom_domain_id required | string <uuid> UUID of the custom-domain link. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Returns one brand by its UUID.
| brand_id required | string <uuid> UUID of the brand. |
BrandResponse
{- "id": "00000000-0000-4000-8000-000000000801",
- "created_at": "2026-08-20T08:10:00Z",
- "updated_at": "2026-08-20T08:10:00Z",
- "lock_version": 0,
- "name": "Alpine Facility Services GmbH",
- "email": "dispatch@example.invalid",
- "phone_number": "+43123456789",
- "linked_custom_domains": [ ]
}Permanently removes the brand and its linked branding assets.
| brand_id required | string <uuid> UUID of the brand. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}JSON Merge Patch (RFC 7386). Fields omitted remain unchanged; fields set to null are cleared (for nullable fields).
| brand_id required | string <uuid> UUID of the brand. |
| lock_version | integer or null <int64> Optimistic-locking version: validated when provided (409 on mismatch); omitting it skips the concurrency check |
| name | string Brand name. Omitted leaves the value unchanged. Explicit null is rejected (422) — name is required and cannot be cleared. |
string or null Brand contact email. Omitted leaves the value unchanged; explicit null clears it. | |
| phone_number | string or null International contact number. An explicit '+' country code is required; common formatting is accepted and normalized to canonical E.164. National numbers are rejected. Omitted leaves the value unchanged; explicit null clears it. |
| theme_id | string or null <uuid> Optional custom theme linked to this brand. Omitted leaves the value unchanged; explicit null clears it. |
UpdateBrandNull
{- "lock_version": 2,
- "email": null,
- "phone_number": "+43 1 234 56 789"
}BrandResponse
{- "id": "00000000-0000-4000-8000-000000000801",
- "created_at": "2026-08-20T08:10:00Z",
- "updated_at": "2026-08-20T08:10:00Z",
- "lock_version": 0,
- "name": "Alpine Facility Services GmbH",
- "email": "dispatch@example.invalid",
- "phone_number": "+43123456789",
- "linked_custom_domains": [ ]
}Removes the current brand logo.
| brand_id required | string <uuid> UUID of the brand. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Returns upload lifecycle status for a brand logo upload session.
| brand_id required | string <uuid> UUID of the brand. |
| file_id required | string <uuid> UUID of the uploaded file. |
UploadedAlpineBrandLogo
{- "file_id": "00000000-0000-4000-8000-000000000811",
- "status": "UPLOADED",
- "logo_applied": true,
}Removes the current brand favicon.
| brand_id required | string <uuid> UUID of the brand. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}Returns upload lifecycle status for a brand favicon upload session.
| brand_id required | string <uuid> UUID of the brand. |
| file_id required | string <uuid> UUID of the uploaded file. |
UploadedAlpineBrandFavicon
{- "file_id": "00000000-0000-4000-8000-000000000812",
- "status": "UPLOADED",
- "favicon_applied": true,
}Returns the default country and default focus point used by geocoding flows.
ViennaGeocodingSettings
{- "default_country": "AT",
- "default_focus_point": {
- "lat": 48.2082,
- "lon": 16.3738
}, - "map": {
- "default_zoom": 13,
- "overview_zoom": 10,
- "default_style": "STREETS"
}
}JSON Merge Patch (RFC 7386). Omitted fields remain unchanged; null resets a field to the default value. Inside map, omitted sub-fields also remain unchanged, so a patch may name a single zoom level. The whole patch is applied atomically: if any field fails validation, none is stored.
| default_country | string or null Default country as ISO 3166-1 alpha-2 code. Omit to leave unchanged; null resets to the default (DE). |
GeocodingFocusPoint (object) or null Default focus point used to bias forward geocoding results. Omit to leave unchanged; null resets to the default (Berlin). | |
UpdateGeocodingMapDefaults (object) or null Map defaults. Omit to leave unchanged; include only the sub-fields you want to change; null resets the whole block to the defaults (zoom 11, overview zoom 5.5, STREETS). |
UpdateDefaultCountryOnly
{- "default_country": "AT"
}UpdatedViennaGeocodingSettings
{- "default_country": "AT",
- "default_focus_point": {
- "lat": 48.2082,
- "lon": 16.3738
}, - "map": {
- "default_zoom": 13,
- "overview_zoom": 10,
- "default_style": "STREETS"
}
}Returns roles the current user can assign, plus their own roles, with enabled grants.
| search | string Example: search=dispatcher Case-insensitive partial match on role name. |
| page | integer >= 0 Default: 0 Page number (0-based). |
| size | integer [ 1 .. 100 ] Default: 20 Example: size=20 Number of items per page (max 100). |
RolesResponse
{- "items": [
- {
- "id": "00000000-0000-4000-8000-000000001101",
- "name": "technician",
- "description": "Field technicians who maintain customer equipment.",
- "grants": [
- "users:read",
- "users:update"
], - "assignable_by_roles": [
- "00000000-0000-4000-8000-000000001100"
], - "member_count": 1,
- "can_assign": true,
- "editable": true,
- "is_system_role": false,
- "lock_version": 0
}, - {
- "id": "00000000-0000-4000-8000-000000001100",
- "name": "owner",
- "description": "Full access to everything in the workspace.",
- "grants": [
- "users:read"
], - "assignable_by_roles": [ ],
- "member_count": 1,
- "can_assign": false,
- "editable": false,
- "is_system_role": true,
- "lock_version": 0
}
], - "page": {
- "size": 20,
- "total_elements": 2,
- "total_pages": 1,
- "number": 0
}
}Creates a role with the provided grants. Grants the caller does not have are ignored.
| name required | string non-empty Role name |
| grants required | Array of strings unique List of grants enabled for this role |
| assignable_by_roles required | Array of strings <uuid> non-empty unique [ items <uuid > ] Role IDs that are allowed to assign this role |
| description | string Optional role description |
CreateTechnicianRole
{- "name": "technician",
- "grants": [
- "users:read",
- "users:update"
], - "assignable_by_roles": [
- "00000000-0000-4000-8000-000000001100"
], - "description": "Field technicians who maintain customer equipment."
}CreateRoleResponse
{- "id": "00000000-0000-4000-8000-000000001101",
- "name": "technician",
- "description": "Field technicians who maintain customer equipment.",
- "grants": [
- "users:read",
- "users:update"
], - "assignable_by_roles": [
- "00000000-0000-4000-8000-000000001100"
], - "member_count": 1,
- "can_assign": true,
- "editable": true,
- "is_system_role": false,
- "lock_version": 0
}Returns a single role by its unique identifier.
| role_id required | string <uuid> Example: 4b3c2d1e-9a8b-4c6d-8e0f-1234567890ab UUID of the role to retrieve |
RoleResponse
{- "id": "00000000-0000-4000-8000-000000001101",
- "name": "technician",
- "description": "Field technicians who maintain customer equipment.",
- "grants": [
- "users:read",
- "users:update"
], - "assignable_by_roles": [
- "00000000-0000-4000-8000-000000001100"
], - "member_count": 1,
- "can_assign": true,
- "editable": true,
- "is_system_role": false,
- "lock_version": 0
}Deletes a role by its unique identifier.
| role_id required | string <uuid> UUID of the role. |
{- "title": "Validation failed",
- "status": 422,
- "detail": "One or more fields failed validation",
- "instance": "string",
- "errors": [
- {
- "type": "string",
- "title": "string",
- "detail": "string",
- "pointer": "#/driver/email",
- "data": {
- "property1": null,
- "property2": null
}
}
], - "data": {
- "property1": null,
- "property2": null
}
}JSON Merge Patch (RFC 7386): omitted fields remain unchanged; a field set to null is cleared (description). Grants the caller does not have are ignored.
| role_id required | string <uuid> UUID of the role. |
| lock_version | integer or null <int64> Optimistic-locking version: validated when provided (409 on mismatch); omitting it skips the concurrency check |
| name | string Role name. Omitted leaves the value unchanged. Explicit null is rejected (422) — name is required and cannot be cleared. |
| grants | Array of strings unique List of grants enabled for this role; replaces the full grant set when provided. Omitted leaves the value unchanged. Explicit null is rejected (422). |
| assignable_by_roles | Array of strings <uuid> unique [ items <uuid > ] Role IDs that are allowed to assign this role; replaces the full set when provided. Omitted leaves the value unchanged. Explicit null is rejected (422). |
| description | string or null Optional role description. Omitted leaves the value unchanged; explicit null clears it. |
UpdateRoleNull
{- "name": "technician",
- "description": null
}UpdateRoleResponse
{- "id": "00000000-0000-4000-8000-000000001101",
- "name": "technician",
- "description": "Field technicians who maintain customer equipment.",
- "grants": [
- "users:read",
- "users:update"
], - "assignable_by_roles": [
- "00000000-0000-4000-8000-000000001100"
], - "member_count": 1,
- "can_assign": true,
- "editable": true,
- "is_system_role": false,
- "lock_version": 0
}Delivered when this happens to a tag.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "tag.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "tag.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "color": "string"
}, - "previous_attributes": { }
}
}Delivered when this happens to a tag.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "tag.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "tag.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "color": "string"
}, - "previous_attributes": { }
}
}Delivered when this happens to a tag.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "tag.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "tag.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a sms gateway.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "sms_gateway.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "sms_gateway.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "type": "string",
- "enabled": true,
- "priority": 0
}, - "previous_attributes": { }
}
}Delivered when this happens to a sms gateway.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "sms_gateway.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "sms_gateway.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "type": "string",
- "enabled": true,
- "priority": 0
}, - "previous_attributes": { }
}
}Delivered when this happens to a sms gateway.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "sms_gateway.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "sms_gateway.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a brand.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "brand.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "brand.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
- "name": "Alpine Facility Services GmbH",
- "email": "contact@alpine-facility-services.example.invalid",
- "phone_number": "+43123456789",
- "logo_file_id": "8d7e9c10-1111-2222-3333-444455556666",
- "theme_id": "ef2b46f3-8ebb-437e-a671-272e4990fbc8"
}, - "previous_attributes": { }
}
}Delivered when this happens to a brand.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "brand.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "brand.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
- "name": "Alpine Facility Services GmbH",
- "email": "contact@alpine-facility-services.example.invalid",
- "phone_number": "+43123456789",
- "logo_file_id": "8d7e9c10-1111-2222-3333-444455556666",
- "theme_id": "ef2b46f3-8ebb-437e-a671-272e4990fbc8"
}, - "previous_attributes": { }
}
}Delivered when this happens to a brand.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "brand.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "brand.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a skill.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "skill.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "skill.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
- "name": "Fingerabdruck",
- "skill": "FINGERPRINT",
- "skill_type": "FINGERPRINT",
- "short_key": "FP"
}, - "previous_attributes": { }
}
}Delivered when this happens to a skill.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "skill.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "skill.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
- "name": "Fingerabdruck",
- "skill": "FINGERPRINT",
- "skill_type": "FINGERPRINT",
- "short_key": "FP"
}, - "previous_attributes": { }
}
}Delivered when this happens to a skill.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "skill.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "skill.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a area.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "area.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "area.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "color": "#3B82F6"
}, - "previous_attributes": { }
}
}Delivered when this happens to a area.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "area.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "area.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "color": "#3B82F6"
}, - "previous_attributes": { }
}
}Delivered when this happens to a area.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "area.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "area.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a measure unit.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "measure_unit.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "measure_unit.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "symbol": "string"
}, - "previous_attributes": { }
}
}Delivered when this happens to a measure unit.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "measure_unit.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "measure_unit.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "symbol": "string"
}, - "previous_attributes": { }
}
}Delivered when this happens to a measure unit.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "measure_unit.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "measure_unit.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a role.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "role.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "role.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Dispatcher",
- "grants_added": [
- "users:delete"
], - "grants_removed": [
- "webhooks:create"
]
}, - "previous_attributes": { }
}
}Delivered when this happens to a user.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "user.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "user.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
- "email": "jonas.leitner@example.invalid",
- "active": true,
- "first_name": "John",
- "last_name": "Doe",
- "phone_number": "+1234567890",
- "role_associations": [
- {
- "role_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
- "role_name": "Driver"
}
]
}, - "previous_attributes": { }
}
}Delivered when this happens to a user.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "user.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "user.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
- "email": "jonas.leitner@example.invalid",
- "active": true,
- "first_name": "John",
- "last_name": "Doe",
- "phone_number": "+1234567890",
- "role_associations": [
- {
- "role_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
- "role_name": "Driver"
}
]
}, - "previous_attributes": { }
}
}Delivered when this happens to a user.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "user.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "user.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a theme.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "theme.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "theme.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "active": true
}, - "previous_attributes": { }
}
}Delivered when this happens to a theme.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "theme.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "theme.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "active": true
}, - "previous_attributes": { }
}
}Delivered when this happens to a theme.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "theme.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "theme.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a file.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "file.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "file.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
- "description": "Profile picture",
- "public_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
- "external_id": "string",
- "is_public": false
}, - "previous_attributes": { }
}
}Delivered when this happens to a file.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "file.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "file.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
- "description": "Profile picture",
- "public_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
- "external_id": "string",
- "is_public": false
}, - "previous_attributes": { }
}
}Delivered when this happens to a file.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "file.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "file.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a document.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "document.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "document.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "state": "ACTIVE",
- "name": "string",
- "description": "string",
- "size": 0,
- "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901",
- "version_id": "9e94c502-ca41-4342-a7f7-af96b444512c",
- "version_number": 0,
- "mime_type": "string",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
- "original_path": "string",
- "conflict_resolution": "string"
}, - "previous_attributes": { }
}
}Delivered when this happens to a document.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "document.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "document.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "state": "ACTIVE",
- "name": "string",
- "description": "string",
- "size": 0,
- "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901",
- "version_id": "9e94c502-ca41-4342-a7f7-af96b444512c",
- "version_number": 0,
- "mime_type": "string",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
- "original_path": "string",
- "conflict_resolution": "string"
}, - "previous_attributes": { }
}
}Delivered when this happens to a document.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "document.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "document.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "state": "ACTIVE",
- "name": "string",
- "description": "string",
- "size": 0,
- "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901",
- "version_id": "9e94c502-ca41-4342-a7f7-af96b444512c",
- "version_number": 0,
- "mime_type": "string",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
- "original_path": "string",
- "conflict_resolution": "string"
}, - "previous_attributes": { }
}
}Delivered when this happens to a document version.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "document.version.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "document.version.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "size": 0,
- "document_id": "b792e8ae-2cb4-4209-85b9-32be4c2fcdd6",
- "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901",
- "version_number": 0,
- "mime_type": "string",
- "change_note": "string"
}, - "previous_attributes": { }
}
}Delivered when this happens to a document permissions.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "document.permissions.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "document.permissions.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "added_count": 0,
- "removed_count": 0,
- "changed_count": 0
}, - "previous_attributes": { }
}
}Delivered when this happens to a folder.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "folder.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "folder.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Inspection reports",
- "kind": "user",
- "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4"
}, - "previous_attributes": { }
}
}Delivered when this happens to a folder.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "folder.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "folder.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Inspection reports",
- "kind": "user",
- "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4"
}, - "previous_attributes": { }
}
}Delivered when this happens to a folder.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "folder.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "folder.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a folder permissions.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "folder.permissions.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "folder.permissions.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "added_count": 0,
- "removed_count": 0,
- "changed_count": 0
}, - "previous_attributes": { }
}
}Delivered when this happens to a comment.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "comment.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "comment.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "state": "ACTIVE",
- "mentions": [
- {
- "type": "user",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "display_name": "Mara Berger",
- "position": 0
}
], - "attachments": [
- {
- "inline": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "mime_type": "string",
- "size_bytes": 0,
- "is_inline": true,
- "position": 0
}
], - "moderation": true,
- "target_type": "co:vehicles",
- "target_id": "d3bcdc92-4191-401b-ad0c-42056c6efab9",
- "author_id": "78424c75-5c41-4b25-9735-3c9f7d05c59e",
- "parent_comment_id": "42e5891d-0323-4706-8826-2064102ce531",
- "root_comment_id": "6cde9fa4-17f0-4a3e-b23f-5a6dc325b9f0",
- "body_markdown": "string",
- "is_moderation": true,
- "edit_reason": "string",
- "last_edited_at": "2019-08-24T14:15:22Z"
}, - "previous_attributes": { }
}
}Delivered when this happens to a comment.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "comment.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "comment.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "state": "ACTIVE",
- "mentions": [
- {
- "type": "user",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "display_name": "Mara Berger",
- "position": 0
}
], - "attachments": [
- {
- "inline": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "mime_type": "string",
- "size_bytes": 0,
- "is_inline": true,
- "position": 0
}
], - "moderation": true,
- "target_type": "co:vehicles",
- "target_id": "d3bcdc92-4191-401b-ad0c-42056c6efab9",
- "author_id": "78424c75-5c41-4b25-9735-3c9f7d05c59e",
- "parent_comment_id": "42e5891d-0323-4706-8826-2064102ce531",
- "root_comment_id": "6cde9fa4-17f0-4a3e-b23f-5a6dc325b9f0",
- "body_markdown": "string",
- "is_moderation": true,
- "edit_reason": "string",
- "last_edited_at": "2019-08-24T14:15:22Z"
}, - "previous_attributes": { }
}
}Delivered when this happens to a comment reaction.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "comment.reaction.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "comment.reaction.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "emoji": "👍",
- "comment_id": "24dbb54d-334d-4b2a-92ae-e15845e5d822",
- "target_type": "co:vehicles",
- "target_id": "d3bcdc92-4191-401b-ad0c-42056c6efab9",
- "comment_author_id": "4eb02608-52da-4633-bc37-f639f0690b7f"
}, - "previous_attributes": { }
}
}Delivered when this happens to a comment reaction.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "comment.reaction.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "comment.reaction.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "emoji": "👍",
- "comment_id": "24dbb54d-334d-4b2a-92ae-e15845e5d822",
- "target_type": "co:vehicles",
- "target_id": "d3bcdc92-4191-401b-ad0c-42056c6efab9",
- "comment_author_id": "4eb02608-52da-4633-bc37-f639f0690b7f"
}, - "previous_attributes": { }
}
}Illustrative custom-object delivery. example stands for the definition's actual slug.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "custom_object.example.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "custom_object.example.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "data": {
- "property1": { },
- "property2": { }
}, - "definition_slug": "invoice",
- "definition_id": "91c1994f-b1db-4fef-840d-7d3ab2984871"
}, - "previous_attributes": { }
}
}Illustrative custom-object delivery. example stands for the definition's actual slug.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "custom_object.example.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "custom_object.example.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "data": {
- "property1": { },
- "property2": { }
}, - "definition_slug": "invoice",
- "definition_id": "91c1994f-b1db-4fef-840d-7d3ab2984871"
}, - "previous_attributes": { }
}
}Illustrative custom-object delivery. example stands for the definition's actual slug.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "custom_object.example.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "custom_object.example.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "data": {
- "property1": { },
- "property2": { }
}, - "definition_slug": "invoice",
- "definition_id": "91c1994f-b1db-4fef-840d-7d3ab2984871"
}, - "previous_attributes": { }
}
}Illustrative custom-object delivery. example stands for the definition's actual slug.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "custom_object.example.permissions.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "custom_object.example.permissions.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "definition_slug": "invoice",
- "changed_by": "3e89c7a5-3fa2-4d93-b1c0-5c0519bb2681",
- "added_count": 0,
- "removed_count": 0,
- "changed_count": 0
}, - "previous_attributes": { }
}
}Delivered when this happens to a custom object definition.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "custom_object_definition.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "custom_object_definition.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "slug": "invoice"
}, - "previous_attributes": { }
}
}Delivered when this happens to a custom object definition.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "custom_object_definition.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "custom_object_definition.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "slug": "invoice"
}, - "previous_attributes": { }
}
}Delivered when this happens to a custom object definition.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "custom_object_definition.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "custom_object_definition.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "slug": "invoice"
}, - "previous_attributes": { }
}
}Delivered when this happens to a device.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "device.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "device.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
- "platform": "IOS",
- "description": "string",
- "phone_number": "+4312345678",
- "provisioning_state": "PROVISIONED"
}, - "previous_attributes": { }
}
}Delivered when this happens to a device.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "device.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "device.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
- "platform": "IOS",
- "description": "string",
- "phone_number": "+4312345678",
- "provisioning_state": "PROVISIONED"
}, - "previous_attributes": { }
}
}Delivered when this happens to a device.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "device.deleted" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "device.deleted",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a vehicle.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "vehicle.created" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "vehicle.created",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}Delivered when this happens to a vehicle.
| webhook-id required | string <uuid> Unique message id (UUID). Stable across retries of the same event — use it as an idempotency key. |
| webhook-timestamp required | string^[0-9]+$ Example: 1787565600 Unix timestamp in seconds at which this delivery attempt was signed. Reject deliveries outside your tolerance window. |
| webhook-signature required | string Example: v1,dGVzdC1zaWduYXR1cmU= Standard Webhooks signature: |
| type required | string Event name: Value: "vehicle.updated" |
| id required | string <uuid> Delivery id, identical to the |
| event_id required | string <uuid> Id of the underlying event. Identical across every endpoint and every retry that delivers it — use it to deduplicate when more than one endpoint feeds one consumer. |
| timestamp required | string <date-time> When the event occurred (ISO 8601, UTC). Not the time this attempt was signed — that is the |
| payload_version required | integer <int32> Version of the payload shape this endpoint is pinned to. Independent of the version of the API used to register the endpoint. Value: 1 |
| tenant_id required | string <uuid> Workspace the event belongs to. |
object (WebhookActor) The principal that caused the event. | |
object (WebhookRequestContext) Tracing handles for the API request that caused this event. | |
required | object The resource this event is about, plus the previous values of any changed fields. |
{- "type": "vehicle.updated",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7",
- "timestamp": "2026-08-24T10:00:00Z",
- "payload_version": 1,
- "tenant_id": "34f5c98e-f430-457b-a812-92637d0c6fd0",
- "actor": {
- "type": "USER",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "request": {
- "id": "8f1c6d2e-3b47-4a91-9f0e-2c5d7a1b4e63",
- "correlation_id": "string"
}, - "data": {
- "object": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}, - "previous_attributes": { }
}
}