Developer preview

Sandtime.io REST API

Use the Sandtime.io REST API from cURL or any standard HTTP client. The current reference documents verified operations across public route paths, plus a machine-readable OpenAPI schema.

When to use REST

The REST API is the right fit when your environment only supports plain HTTP, when you want cURL examples, or when you need direct control over payloads and endpoint URLs.

For AI agents, Sandtime.io still recommends the MCP server first because MCP exposes higher-level workflows and more ergonomic tool contracts. Reach for REST when MCP is unavailable or when the user explicitly asks for raw HTTP.

  • Use REST when you need direct HTTP control, cURL scripts, CI jobs, or a standard API client.
  • Use the OpenAPI JSON when you want to generate clients, validate requests, or feed the schema to tooling.
  • Use MCP instead when an AI client can call tools directly and benefit from higher-level workflows.

Authenticate with a Bearer token

REST requests target your organization hostname directly, for example https://acme.sandtime.io/api. The hostname identifies the workspace, so REST does not require the X-Sandtime-Organization header used by MCP.

curl -X GET 'https://your-organization.sandtime.io/api/auth' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Authentication is still in developer preview. Today you obtain the Bearer token by copying it from the Sandtime.io session cookie. This matches the current MCP authentication flow, and a dedicated token flow is still being built.

Machine-readable docs and API conventions

Everything below is backed by the same shared route registry that also generates the OpenAPI JSON.

OpenAPI JSON

A downloadable OpenAPI schema for code generation, validators, and API tooling.

https://sandtime.io/api/openapi.json

SKILL.md

A machine-readable integration guide for agents deciding between MCP and raw HTTP.

https://sandtime.io/SKILL.md

MCP docs

The higher-level integration path for Claude Code, Codex, and other MCP clients.

https://sandtime.io/mcp

Request conventions

  • Base URL: one workspace per hostname, for example https://acme.sandtime.io/api.
  • Authentication: send Authorization: Bearer <token>. Today the token is copied from the sandtime_access_token cookie.
  • Format: requests and responses use JSON. Route-specific examples below mirror the current server implementation.
  • Workflow: resolve IDs with read requests before writes so you never guess project, user, member, or report identifiers.

Route groups

Jump into a namespace, then inspect each route path, supported methods, request body examples, and sample responses.

Workspace

Workspace discovery, organization settings, and authentication helpers.

Activities

Time entry CRUD for manual logging, timers, and admin corrections.

Reports

Saved report definitions for dashboards, billing, and exports.

Geofences

Geofence definitions plus mobile enter and exit triggers.

Timesheets

Explicit timesheet locks, automatic lock execution, and reminder delivery.

Workspace

Workspace discovery, organization settings, and authentication helpers.

/auth

Authentication snapshot

Read the current cookie-backed auth snapshot or list the organizations available to the signed-in user.

GET

Get the current auth snapshot

Returns the current user email, active organization domain, and the same Bearer token currently extracted from the session cookie.

Response status: 200Operation ID: get-auth
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/auth' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "domain": "acme",
  "email": "alex.rivera@example.com",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.example"
}
/organizations

Organizations

List the active organizations available to the signed-in user account.

GET

List active organizations

Returns the active workspaces available to the current user across Sandtime.io.

Response status: 200Operation ID: get-organizations
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/organizations' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
[
  {
    "active": true,
    "domain": "acme",
    "name": "Acme Studio"
  },
  {
    "active": true,
    "domain": "northwind",
    "name": "Northwind Consulting"
  }
]
/organization

Organization settings

Read, update, or permanently remove the current organization.

GET

Get organization settings

Returns the organization settings loaded for the current hostname.

Response status: 200Operation ID: get-organization
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/organization' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "coreHours": {
    "end": "17:00",
    "start": "09:00"
  },
  "currency": "USD",
  "holidays": {
    "country": "US",
    "excluded": []
  },
  "id": "8a4affba-df59-47bd-8173-d175e76efd15",
  "lockingTimesheets": {
    "enabled": false,
    "timeZone": null,
    "week": null,
    "year": null
  },
  "name": "Acme Studio",
  "notes": "Weekly client delivery team.",
  "onboarding": {
    "assignMembers": {
      "done": true,
      "viewed": true
    },
    "inviteMembers": {
      "done": true,
      "viewed": true
    },
    "organization": {
      "done": true,
      "viewed": true
    },
    "preferences": {
      "done": false,
      "viewed": true
    },
    "projects": {
      "done": true,
      "viewed": true
    }
  },
  "plan": "free",
  "rounding": {
    "enabled": false,
    "interval": 900000,
    "mode": "NEAREST"
  },
  "timeZone": "Europe/Warsaw"
}
PUT

Update organization settings

Updates mutable organization settings such as currency, notes, core hours, holidays, rounding, and timesheet locking.

Response status: 200Operation ID: put-organization
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/organization' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "coreHours": {
    "end": "16:00",
    "start": "08:00"
  },
  "currency": "EUR",
  "notes": "Updated delivery schedule for the summer quarter.",
  "rounding": {
    "enabled": true,
    "interval": 900000,
    "mode": "NEAREST"
  },
  "timeZone": "Europe/Warsaw"
}'
Request body example
{
  "coreHours": {
    "end": "16:00",
    "start": "08:00"
  },
  "currency": "EUR",
  "notes": "Updated delivery schedule for the summer quarter.",
  "rounding": {
    "enabled": true,
    "interval": 900000,
    "mode": "NEAREST"
  },
  "timeZone": "Europe/Warsaw"
}
Response example
{
  "coreHours": {
    "end": "17:00",
    "start": "09:00"
  },
  "currency": "USD",
  "holidays": {
    "country": "US",
    "excluded": []
  },
  "id": "8a4affba-df59-47bd-8173-d175e76efd15",
  "lockingTimesheets": {
    "enabled": false,
    "timeZone": null,
    "week": null,
    "year": null
  },
  "name": "Acme Studio",
  "notes": "Weekly client delivery team.",
  "onboarding": {
    "assignMembers": {
      "done": true,
      "viewed": true
    },
    "inviteMembers": {
      "done": true,
      "viewed": true
    },
    "organization": {
      "done": true,
      "viewed": true
    },
    "preferences": {
      "done": false,
      "viewed": true
    },
    "projects": {
      "done": true,
      "viewed": true
    }
  },
  "plan": "free",
  "rounding": {
    "enabled": false,
    "interval": 900000,
    "mode": "NEAREST"
  },
  "timeZone": "Europe/Warsaw"
}
DELETE

Delete the current organization

Deletes the current organization. This action is restricted to administrators and may return a redirect URL for follow-up account cleanup.

Response status: 200Operation ID: delete-organization
cURL example
curl -X DELETE 'https://your-organization.sandtime.io/api/organization' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "domain": "acme",
  "redirectUrl": "https://sandtime.io/offboarding-thank-you"
}
/organization/rename

Organization rename

Rename the current organization subdomain to a new available workspace hostname.

POST

Rename the organization subdomain

Starts an organization rename from the current subdomain to the new desired subdomain.

Response status: 200Operation ID: post-organization-rename
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/organization/rename' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "domain": "acme-europe"
}'
Request body example
{
  "domain": "acme-europe"
}
Response example
{
  "domain": "acme-europe"
}

Activities

Time entry CRUD for manual logging, timers, and admin corrections.

/activities

Activity collection

List all activities visible to the current workspace context or create a new time entry.

GET

List activities

Returns an ID-keyed map of activity records visible to the current user.

Response status: 200Operation ID: get-activities
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/activities' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "c2dbd56f-0f09-4bf8-87ae-a1c8d7e5f302": {
    "billable": true,
    "endedAt": "2026-07-03T08:30:00.000Z",
    "id": "c2dbd56f-0f09-4bf8-87ae-a1c8d7e5f302",
    "name": "Implement API docs page",
    "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "startedAt": "2026-07-03T07:00:00.000Z",
    "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
  }
}
POST

Create an activity

Creates a new activity. Send `pending: true` with no `endedAt` when you want an open timer.

Response status: 200Operation ID: post-activities
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/activities' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "billable": true,
  "endedAt": "2026-07-03T10:30:00+02:00",
  "name": "Implement API docs page",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "startedAt": "2026-07-03T09:00:00+02:00"
}'
Request body example
{
  "billable": true,
  "endedAt": "2026-07-03T10:30:00+02:00",
  "name": "Implement API docs page",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "startedAt": "2026-07-03T09:00:00+02:00"
}
Response example
{
  "billable": true,
  "endedAt": "2026-07-03T08:30:00.000Z",
  "id": "c2dbd56f-0f09-4bf8-87ae-a1c8d7e5f302",
  "name": "Implement API docs page",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "startedAt": "2026-07-03T07:00:00.000Z",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
}
/activities/{activityId}

Single activity

Read, update, or delete a single activity by ID.

Path parameters

  • activityId: The activity identifier.
GET

Get an activity

Returns one activity record when the ID exists and the current user can see it.

Response status: 200Operation ID: get-activities-activityId
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/activities/c2dbd56f-0f09-4bf8-87ae-a1c8d7e5f302' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "billable": true,
  "endedAt": "2026-07-03T08:30:00.000Z",
  "id": "c2dbd56f-0f09-4bf8-87ae-a1c8d7e5f302",
  "name": "Implement API docs page",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "startedAt": "2026-07-03T07:00:00.000Z",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
}
PUT

Update an activity

Updates one activity. Typical changes include timestamps, billable status, title, and project assignment.

Response status: 200Operation ID: put-activities-activityId
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/activities/c2dbd56f-0f09-4bf8-87ae-a1c8d7e5f302' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "billable": false,
  "endedAt": "2026-07-03T11:00:00+02:00",
  "name": "Polish the REST API guide"
}'
Request body example
{
  "billable": false,
  "endedAt": "2026-07-03T11:00:00+02:00",
  "name": "Polish the REST API guide"
}
Response example
{
  "billable": false,
  "endedAt": "2026-07-03T09:00:00.000Z",
  "id": "c2dbd56f-0f09-4bf8-87ae-a1c8d7e5f302",
  "name": "Polish the REST API guide",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "startedAt": "2026-07-03T07:00:00.000Z",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
}
DELETE

Delete an activity

Deletes one activity by ID.

Response status: 200Operation ID: delete-activities-activityId
cURL example
curl -X DELETE 'https://your-organization.sandtime.io/api/activities/c2dbd56f-0f09-4bf8-87ae-a1c8d7e5f302' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{}

Projects

Projects, memberships, and project-specific revenue rates.

/projects

Project collection

List all projects visible to the user or create a new project.

GET

List projects

Returns an ID-keyed map of projects.

Response status: 200Operation ID: get-projects
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/projects' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001": {
    "archived": false,
    "avatar": null,
    "billable": true,
    "id": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "name": "Website refresh",
    "notes": "Main client delivery project."
  }
}
POST

Create a project

Creates a project and automatically adds the creating administrator as a project member.

Response status: 200Operation ID: post-projects
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/projects' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "billable": true,
  "name": "Website refresh",
  "notes": "Main client delivery project."
}'
Request body example
{
  "billable": true,
  "name": "Website refresh",
  "notes": "Main client delivery project."
}
Response example
{
  "archived": false,
  "avatar": null,
  "billable": true,
  "id": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "name": "Website refresh",
  "notes": "Main client delivery project."
}
/projects/{projectId}

Single project

Read, update, or delete a single project.

Path parameters

  • projectId: The project identifier.
GET

Get a project

Returns one project by ID.

Response status: 200Operation ID: get-projects-projectId
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "archived": false,
  "avatar": null,
  "billable": true,
  "id": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "name": "Website refresh",
  "notes": "Main client delivery project."
}
PUT

Update a project

Updates project metadata such as notes, billable status, archived state, or avatar.

Response status: 200Operation ID: put-projects-projectId
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "billable": false,
  "notes": "Internal redesign and QA support."
}'
Request body example
{
  "billable": false,
  "notes": "Internal redesign and QA support."
}
Response example
{
  "archived": false,
  "avatar": null,
  "billable": false,
  "id": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "name": "Website refresh",
  "notes": "Internal redesign and QA support."
}
DELETE

Delete a project

Deletes a project permanently.

Response status: 200Operation ID: delete-projects-projectId
cURL example
curl -X DELETE 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{}
/projects/{projectId}/members

Project members

List or create project members inside one project.

Path parameters

  • projectId: The project identifier.
GET

List project members

Returns an ID-keyed map of members assigned to the project.

Response status: 200Operation ID: get-projects-projectId-members
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04": {
    "archived": false,
    "assignedBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
    "id": "3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04",
    "notes": "Frontend owner",
    "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "role": "Administrator",
    "tags": [
      "design-system",
      "client-facing"
    ],
    "title": "Frontend Lead",
    "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
  }
}
POST

Create a project member

Assigns a user to the project and optionally stores role, title, notes, and tags.

Response status: 200Operation ID: post-projects-projectId-members
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "notes": "Frontend owner",
  "role": "Administrator",
  "tags": [
    "design-system",
    "client-facing"
  ],
  "title": "Frontend Lead",
  "userId": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af"
}'
Request body example
{
  "notes": "Frontend owner",
  "role": "Administrator",
  "tags": [
    "design-system",
    "client-facing"
  ],
  "title": "Frontend Lead",
  "userId": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af"
}
Response example
{
  "archived": false,
  "assignedBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04",
  "notes": "Frontend owner",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "role": "User",
  "tags": [
    "design-system",
    "client-facing"
  ],
  "title": "Product Designer",
  "userId": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af"
}
/projects/{projectId}/members/{memberId}

Single project member

Read, update, or remove a single project member record.

Path parameters

  • projectId: The project identifier.
  • memberId: The project member identifier.
GET

Get a project member

Returns one project membership by member ID.

Response status: 200Operation ID: get-projects-projectId-members-memberId
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members/3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "archived": false,
  "assignedBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04",
  "notes": "Frontend owner",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "role": "Administrator",
  "tags": [
    "design-system",
    "client-facing"
  ],
  "title": "Frontend Lead",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
}
PUT

Update a project member

Updates role, title, tags, notes, or archived state for one project member.

Response status: 200Operation ID: put-projects-projectId-members-memberId
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members/3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "notes": "Delivery owner",
  "role": "User",
  "tags": [
    "handover",
    "qa"
  ],
  "title": "Delivery Manager"
}'
Request body example
{
  "notes": "Delivery owner",
  "role": "User",
  "tags": [
    "handover",
    "qa"
  ],
  "title": "Delivery Manager"
}
Response example
{
  "archived": false,
  "assignedBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04",
  "notes": "Delivery owner",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "role": "User",
  "tags": [
    "handover",
    "qa"
  ],
  "title": "Delivery Manager",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
}
DELETE

Delete a project member

Removes the member from the project.

Response status: 200Operation ID: delete-projects-projectId-members-memberId
cURL example
curl -X DELETE 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members/3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{}
/projects/{projectId}/members/{memberId}/rates/revenue

Member revenue rates

List or create revenue rates for one project member.

Path parameters

  • projectId: The project identifier.
  • memberId: The project member identifier.
GET

List member revenue rates

Returns an ID-keyed map of revenue rates for the selected project member.

Response status: 200Operation ID: get-projects-projectId-members-memberId-rates-revenue
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members/3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04/rates/revenue' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "e6dd7425-f0ef-403c-8f21-5fe1931cc9a9": {
    "currency": "USD",
    "from": "2026-07-01T00:00:00.000Z",
    "id": "e6dd7425-f0ef-403c-8f21-5fe1931cc9a9",
    "memberId": "3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04",
    "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "taxRate": 23,
    "to": "2026-12-31T23:59:59.000Z",
    "value": 145
  }
}
POST

Create a member revenue rate

Creates a dated revenue rate window for a project member.

Response status: 200Operation ID: post-projects-projectId-members-memberId-rates-revenue
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members/3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04/rates/revenue' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "currency": "USD",
  "from": "2026-07-01T00:00:00+02:00",
  "taxRate": 23,
  "to": "2026-12-31T23:59:59+01:00",
  "value": 145
}'
Request body example
{
  "currency": "USD",
  "from": "2026-07-01T00:00:00+02:00",
  "taxRate": 23,
  "to": "2026-12-31T23:59:59+01:00",
  "value": 145
}
Response example
{
  "currency": "USD",
  "from": "2026-07-01T00:00:00.000Z",
  "id": "e6dd7425-f0ef-403c-8f21-5fe1931cc9a9",
  "memberId": "3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "taxRate": 23,
  "to": "2026-12-31T23:59:59.000Z",
  "value": 145
}
/projects/{projectId}/members/{memberId}/rates/revenue/{revenueId}

Single member revenue rate

Read, update, or delete one revenue rate window.

Path parameters

  • projectId: The project identifier.
  • memberId: The project member identifier.
  • revenueId: The revenue rate identifier.
GET

Get a member revenue rate

Returns one revenue rate record.

Response status: 200Operation ID: get-projects-projectId-members-memberId-rates-revenue-revenueId
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members/3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04/rates/revenue/e6dd7425-f0ef-403c-8f21-5fe1931cc9a9' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "currency": "USD",
  "from": "2026-07-01T00:00:00.000Z",
  "id": "e6dd7425-f0ef-403c-8f21-5fe1931cc9a9",
  "memberId": "3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "taxRate": 23,
  "to": "2026-12-31T23:59:59.000Z",
  "value": 145
}
PUT

Update a member revenue rate

Updates one revenue rate window.

Response status: 200Operation ID: put-projects-projectId-members-memberId-rates-revenue-revenueId
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members/3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04/rates/revenue/e6dd7425-f0ef-403c-8f21-5fe1931cc9a9' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "currency": "USD",
  "from": "2026-07-01T00:00:00+02:00",
  "taxRate": 23,
  "to": "2026-12-31T23:59:59+01:00",
  "value": 155
}'
Request body example
{
  "currency": "USD",
  "from": "2026-07-01T00:00:00+02:00",
  "taxRate": 23,
  "to": "2026-12-31T23:59:59+01:00",
  "value": 155
}
Response example
{
  "currency": "USD",
  "from": "2026-07-01T00:00:00.000Z",
  "id": "e6dd7425-f0ef-403c-8f21-5fe1931cc9a9",
  "memberId": "3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "taxRate": 23,
  "to": "2026-12-31T23:59:59.000Z",
  "value": 155
}
DELETE

Delete a member revenue rate

Deletes one revenue rate record.

Response status: 200Operation ID: delete-projects-projectId-members-memberId-rates-revenue-revenueId
cURL example
curl -X DELETE 'https://your-organization.sandtime.io/api/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members/3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04/rates/revenue/e6dd7425-f0ef-403c-8f21-5fe1931cc9a9' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{}

Users

Users, personal preferences, and organization-level cost rates.

/users

User collection

List all users in the current organization or invite a new member.

GET

List users

Returns an ID-keyed map of organization users.

Response status: 200Operation ID: get-users
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/users' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d": {
    "archived": false,
    "avatar": null,
    "email": "alex.rivera@example.com",
    "id": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
    "name": "Alex Rivera",
    "phone": "+1 415 555 0102",
    "role": "Administrator",
    "title": "Operations Lead"
  }
}
POST

Create or invite a user

Invites a user to the current organization. Existing users are re-invited instead of duplicated.

Response status: 200Operation ID: post-users
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/users' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "sam.lee@example.com",
  "name": "Sam Lee",
  "role": "User",
  "title": "Product Designer"
}'
Request body example
{
  "email": "sam.lee@example.com",
  "name": "Sam Lee",
  "role": "User",
  "title": "Product Designer"
}
Response example
{
  "archived": false,
  "avatar": null,
  "email": "sam.lee@example.com",
  "id": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "name": "Sam Lee",
  "phone": "+1 415 555 0102",
  "role": "User",
  "title": "Product Designer"
}
/users/{userId}

Single user

Read, update, or remove a single user.

Path parameters

  • userId: The user identifier.
GET

Get a user

Returns one user record.

Response status: 200Operation ID: get-users-userId
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/users/2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "archived": false,
  "avatar": null,
  "email": "alex.rivera@example.com",
  "id": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "name": "Alex Rivera",
  "phone": "+1 415 555 0102",
  "role": "Administrator",
  "title": "Operations Lead"
}
PUT

Update a user

Updates one user. Administrators can change role and archived state. Users can update their own profile fields.

Response status: 200Operation ID: put-users-userId
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/users/2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "archived": false,
  "phone": "+1 415 555 0188",
  "role": "Administrator",
  "title": "Head of Operations"
}'
Request body example
{
  "archived": false,
  "phone": "+1 415 555 0188",
  "role": "Administrator",
  "title": "Head of Operations"
}
Response example
{
  "archived": false,
  "avatar": null,
  "email": "alex.rivera@example.com",
  "id": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "name": "Alex Rivera",
  "phone": "+1 415 555 0188",
  "role": "Administrator",
  "title": "Head of Operations"
}
DELETE

Delete a user

Permanently removes a user and their associated workspace data after server-side validations pass.

Response status: 200Operation ID: delete-users-userId
cURL example
curl -X DELETE 'https://your-organization.sandtime.io/api/users/2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{}
/users/{userId}/preferences

User preferences

Read or update personal preferences for one user.

Path parameters

  • userId: The user identifier.
GET

Get user preferences

Returns the preference document for the user. Users can only read their own preferences.

Response status: 200Operation ID: get-users-userId-preferences
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/users/2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d/preferences' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "dateTimeFormat": {
    "clock24Hour": true,
    "numeric": true,
    "showSeconds": false
  },
  "desktop": {
    "startTrackingOnStartup": false,
    "stopTrackingOnShutdown": true
  },
  "durationFormat": {
    "compact": false,
    "mode": "HOURS_MINUTES",
    "showSeconds": false
  },
  "locale": "en-US",
  "notifications": {
    "activityCreated": {
      "dashboard": true,
      "email": false,
      "popup": true
    },
    "monthlyGoalReached": {
      "dashboard": true,
      "email": true,
      "popup": true
    }
  },
  "timeZone": "Europe/Warsaw"
}
PUT

Update user preferences

Updates the user preference document with locale, formatting, desktop, notification, or time-zone changes.

Response status: 200Operation ID: put-users-userId-preferences
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/users/2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d/preferences' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "locale": "pl-PL",
  "notifications": {
    "monthlyGoalReached": {
      "dashboard": true,
      "email": true,
      "popup": false
    }
  },
  "timeZone": "Europe/Warsaw"
}'
Request body example
{
  "locale": "pl-PL",
  "notifications": {
    "monthlyGoalReached": {
      "dashboard": true,
      "email": true,
      "popup": false
    }
  },
  "timeZone": "Europe/Warsaw"
}
Response example
{
  "dateTimeFormat": {
    "clock24Hour": true,
    "numeric": true,
    "showSeconds": false
  },
  "desktop": {
    "startTrackingOnStartup": false,
    "stopTrackingOnShutdown": true
  },
  "durationFormat": {
    "compact": false,
    "mode": "HOURS_MINUTES",
    "showSeconds": false
  },
  "locale": "pl-PL",
  "notifications": {
    "activityCreated": {
      "dashboard": true,
      "email": false,
      "popup": true
    },
    "monthlyGoalReached": {
      "dashboard": true,
      "email": true,
      "popup": true
    }
  },
  "timeZone": "Europe/Warsaw"
}
/users/{userId}/rates/cost

User cost rates

List or create cost-rate windows for one user.

Path parameters

  • userId: The user identifier.
GET

List user cost rates

Returns an ID-keyed map of cost rates for the user.

Response status: 200Operation ID: get-users-userId-rates-cost
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/users/2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d/rates/cost' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "7bc0f6d1-d6a8-4718-8e64-b3ddcfe35334": {
    "currency": "USD",
    "from": "2026-07-01T00:00:00.000Z",
    "id": "7bc0f6d1-d6a8-4718-8e64-b3ddcfe35334",
    "taxRate": 0,
    "to": "2026-12-31T23:59:59.000Z",
    "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
    "value": 65
  }
}
POST

Create a user cost rate

Creates a dated cost-rate window for the user.

Response status: 200Operation ID: post-users-userId-rates-cost
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/users/2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d/rates/cost' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "currency": "USD",
  "from": "2026-07-01T00:00:00+02:00",
  "taxRate": 0,
  "to": "2026-12-31T23:59:59+01:00",
  "value": 65
}'
Request body example
{
  "currency": "USD",
  "from": "2026-07-01T00:00:00+02:00",
  "taxRate": 0,
  "to": "2026-12-31T23:59:59+01:00",
  "value": 65
}
Response example
{
  "currency": "USD",
  "from": "2026-07-01T00:00:00.000Z",
  "id": "7bc0f6d1-d6a8-4718-8e64-b3ddcfe35334",
  "taxRate": 0,
  "to": "2026-12-31T23:59:59.000Z",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "value": 65
}
/users/{userId}/rates/cost/{costId}

Single user cost rate

Read, update, or delete one cost-rate window.

Path parameters

  • userId: The user identifier.
  • costId: The cost rate identifier.
GET

Get a user cost rate

Returns one user cost-rate record.

Response status: 200Operation ID: get-users-userId-rates-cost-costId
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/users/2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d/rates/cost/7bc0f6d1-d6a8-4718-8e64-b3ddcfe35334' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "currency": "USD",
  "from": "2026-07-01T00:00:00.000Z",
  "id": "7bc0f6d1-d6a8-4718-8e64-b3ddcfe35334",
  "taxRate": 0,
  "to": "2026-12-31T23:59:59.000Z",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "value": 65
}
PUT

Update a user cost rate

Updates one user cost-rate window.

Response status: 200Operation ID: put-users-userId-rates-cost-costId
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/users/2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d/rates/cost/7bc0f6d1-d6a8-4718-8e64-b3ddcfe35334' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "currency": "USD",
  "from": "2026-07-01T00:00:00+02:00",
  "taxRate": 0,
  "to": "2026-12-31T23:59:59+01:00",
  "value": 72
}'
Request body example
{
  "currency": "USD",
  "from": "2026-07-01T00:00:00+02:00",
  "taxRate": 0,
  "to": "2026-12-31T23:59:59+01:00",
  "value": 72
}
Response example
{
  "currency": "USD",
  "from": "2026-07-01T00:00:00.000Z",
  "id": "7bc0f6d1-d6a8-4718-8e64-b3ddcfe35334",
  "taxRate": 0,
  "to": "2026-12-31T23:59:59.000Z",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "value": 72
}
DELETE

Delete a user cost rate

Deletes one user cost-rate record.

Response status: 200Operation ID: delete-users-userId-rates-cost-costId
cURL example
curl -X DELETE 'https://your-organization.sandtime.io/api/users/2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d/rates/cost/7bc0f6d1-d6a8-4718-8e64-b3ddcfe35334' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{}

Reports

Saved report definitions for dashboards, billing, and exports.

/reports

Report collection

List saved reports or create a new report definition.

GET

List reports

Returns an ID-keyed map of saved reports.

Response status: 200Operation ID: get-reports
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/reports' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "6b0dfe58-9c80-4d8d-8a9f-9e48983f4e01": {
    "dimensions": [
      "project"
    ],
    "end": "2026-07-31T21:59:59.000Z",
    "filters": [],
    "hideEmptyRows": true,
    "id": "6b0dfe58-9c80-4d8d-8a9f-9e48983f4e01",
    "metrics": [
      "time",
      "billable"
    ],
    "name": "July project summary",
    "period": "custom",
    "pinned": true,
    "selectedProjectMembers": null,
    "selectedProjects": [
      "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
      "58f5aa89-aed2-4a67-8808-d85ef4034f42"
    ],
    "showArchivedMembers": false,
    "showArchivedProjects": false,
    "start": "2026-06-30T22:00:00.000Z",
    "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
  }
}
POST

Create a report

Creates a saved report configuration for the current user.

Response status: 200Operation ID: post-reports
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/reports' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "dimensions": [
    "project"
  ],
  "end": "2026-07-31T23:59:59+02:00",
  "filters": [],
  "hideEmptyRows": true,
  "metrics": [
    "time",
    "billable"
  ],
  "name": "July project summary",
  "period": "custom",
  "selectedProjectMembers": null,
  "selectedProjects": [
    "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "58f5aa89-aed2-4a67-8808-d85ef4034f42"
  ],
  "showArchivedMembers": false,
  "showArchivedProjects": false,
  "start": "2026-07-01T00:00:00+02:00"
}'
Request body example
{
  "dimensions": [
    "project"
  ],
  "end": "2026-07-31T23:59:59+02:00",
  "filters": [],
  "hideEmptyRows": true,
  "metrics": [
    "time",
    "billable"
  ],
  "name": "July project summary",
  "period": "custom",
  "selectedProjectMembers": null,
  "selectedProjects": [
    "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "58f5aa89-aed2-4a67-8808-d85ef4034f42"
  ],
  "showArchivedMembers": false,
  "showArchivedProjects": false,
  "start": "2026-07-01T00:00:00+02:00"
}
Response example
{
  "dimensions": [
    "project"
  ],
  "end": "2026-07-31T21:59:59.000Z",
  "filters": [],
  "hideEmptyRows": true,
  "id": "6b0dfe58-9c80-4d8d-8a9f-9e48983f4e01",
  "metrics": [
    "time",
    "billable"
  ],
  "name": "July project summary",
  "period": "custom",
  "pinned": true,
  "selectedProjectMembers": null,
  "selectedProjects": [
    "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "58f5aa89-aed2-4a67-8808-d85ef4034f42"
  ],
  "showArchivedMembers": false,
  "showArchivedProjects": false,
  "start": "2026-06-30T22:00:00.000Z",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
}
/reports/{reportId}

Single report

Read, update, or delete a single report definition.

Path parameters

  • reportId: The report identifier.
GET

Get a report

Returns one report configuration.

Response status: 200Operation ID: get-reports-reportId
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/reports/6b0dfe58-9c80-4d8d-8a9f-9e48983f4e01' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "dimensions": [
    "project"
  ],
  "end": "2026-07-31T21:59:59.000Z",
  "filters": [],
  "hideEmptyRows": true,
  "id": "6b0dfe58-9c80-4d8d-8a9f-9e48983f4e01",
  "metrics": [
    "time",
    "billable"
  ],
  "name": "July project summary",
  "period": "custom",
  "pinned": true,
  "selectedProjectMembers": null,
  "selectedProjects": [
    "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "58f5aa89-aed2-4a67-8808-d85ef4034f42"
  ],
  "showArchivedMembers": false,
  "showArchivedProjects": false,
  "start": "2026-06-30T22:00:00.000Z",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
}
PUT

Update a report

Updates one saved report.

Response status: 200Operation ID: put-reports-reportId
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/reports/6b0dfe58-9c80-4d8d-8a9f-9e48983f4e01' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "dimensions": [
    "project"
  ],
  "end": "2026-07-31T23:59:59+02:00",
  "filters": [],
  "hideEmptyRows": true,
  "metrics": [
    "time",
    "billable"
  ],
  "name": "July project summary",
  "period": "custom",
  "selectedProjectMembers": null,
  "selectedProjects": [
    "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "58f5aa89-aed2-4a67-8808-d85ef4034f42"
  ],
  "showArchivedMembers": false,
  "showArchivedProjects": false,
  "start": "2026-07-01T00:00:00+02:00",
  "pinned": true
}'
Request body example
{
  "dimensions": [
    "project"
  ],
  "end": "2026-07-31T23:59:59+02:00",
  "filters": [],
  "hideEmptyRows": true,
  "metrics": [
    "time",
    "billable"
  ],
  "name": "July project summary",
  "period": "custom",
  "selectedProjectMembers": null,
  "selectedProjects": [
    "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "58f5aa89-aed2-4a67-8808-d85ef4034f42"
  ],
  "showArchivedMembers": false,
  "showArchivedProjects": false,
  "start": "2026-07-01T00:00:00+02:00",
  "pinned": true
}
Response example
{
  "dimensions": [
    "project"
  ],
  "end": "2026-07-31T21:59:59.000Z",
  "filters": [],
  "hideEmptyRows": true,
  "id": "6b0dfe58-9c80-4d8d-8a9f-9e48983f4e01",
  "metrics": [
    "time",
    "billable"
  ],
  "name": "July project summary",
  "period": "custom",
  "pinned": true,
  "selectedProjectMembers": null,
  "selectedProjects": [
    "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "58f5aa89-aed2-4a67-8808-d85ef4034f42"
  ],
  "showArchivedMembers": false,
  "showArchivedProjects": false,
  "start": "2026-06-30T22:00:00.000Z",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
}
DELETE

Delete a report

Deletes a saved report.

Response status: 200Operation ID: delete-reports-reportId
cURL example
curl -X DELETE 'https://your-organization.sandtime.io/api/reports/6b0dfe58-9c80-4d8d-8a9f-9e48983f4e01' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{}

Geofences

Geofence definitions plus mobile enter and exit triggers.

/geofences

Geofence collection

List geofences or create a new geofence rule.

GET

List geofences

Returns an ID-keyed map of geofences.

Response status: 200Operation ID: get-geofences
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/geofences' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "cf6b0bd6-dbbf-4ef5-98a7-7ae04e0eb18c": {
    "enterAction": "START_TRACKING_PROJECT",
    "exitAction": "STOP_TRACKING",
    "id": "cf6b0bd6-dbbf-4ef5-98a7-7ae04e0eb18c",
    "latitude": 52.2297,
    "longitude": 21.0122,
    "name": "Warsaw office",
    "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "radius": 120
  }
}
POST

Create a geofence

Creates a geofence with enter and exit actions.

Response status: 200Operation ID: post-geofences
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/geofences' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "enterAction": "START_TRACKING_PROJECT",
  "exitAction": "STOP_TRACKING",
  "latitude": 52.2297,
  "longitude": 21.0122,
  "name": "Warsaw office",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "radius": 120
}'
Request body example
{
  "enterAction": "START_TRACKING_PROJECT",
  "exitAction": "STOP_TRACKING",
  "latitude": 52.2297,
  "longitude": 21.0122,
  "name": "Warsaw office",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "radius": 120
}
Response example
{
  "enterAction": "START_TRACKING_PROJECT",
  "exitAction": "STOP_TRACKING",
  "id": "cf6b0bd6-dbbf-4ef5-98a7-7ae04e0eb18c",
  "latitude": 52.2297,
  "longitude": 21.0122,
  "name": "Warsaw office",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "radius": 120
}
/geofences/{geofenceId}

Single geofence

Read, update, or delete one geofence.

Path parameters

  • geofenceId: The geofence identifier.
GET

Get a geofence

Returns one geofence by ID.

Response status: 200Operation ID: get-geofences-geofenceId
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/geofences/cf6b0bd6-dbbf-4ef5-98a7-7ae04e0eb18c' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "enterAction": "START_TRACKING_PROJECT",
  "exitAction": "STOP_TRACKING",
  "id": "cf6b0bd6-dbbf-4ef5-98a7-7ae04e0eb18c",
  "latitude": 52.2297,
  "longitude": 21.0122,
  "name": "Warsaw office",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "radius": 120
}
PUT

Update a geofence

Updates one geofence.

Response status: 200Operation ID: put-geofences-geofenceId
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/geofences/cf6b0bd6-dbbf-4ef5-98a7-7ae04e0eb18c' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "enterAction": "START_TRACKING_PROJECT",
  "exitAction": "STOP_TRACKING",
  "latitude": 52.2297,
  "longitude": 21.0122,
  "name": "Warsaw office",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "radius": 150
}'
Request body example
{
  "enterAction": "START_TRACKING_PROJECT",
  "exitAction": "STOP_TRACKING",
  "latitude": 52.2297,
  "longitude": 21.0122,
  "name": "Warsaw office",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "radius": 150
}
Response example
{
  "enterAction": "START_TRACKING_PROJECT",
  "exitAction": "STOP_TRACKING",
  "id": "cf6b0bd6-dbbf-4ef5-98a7-7ae04e0eb18c",
  "latitude": 52.2297,
  "longitude": 21.0122,
  "name": "Warsaw office",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "radius": 150
}
DELETE

Delete a geofence

Deletes one geofence.

Response status: 200Operation ID: delete-geofences-geofenceId
cURL example
curl -X DELETE 'https://your-organization.sandtime.io/api/geofences/cf6b0bd6-dbbf-4ef5-98a7-7ae04e0eb18c' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{}
/geofencing/enter

Geofence enter trigger

Signal that a device entered a geofence and let Sandtime.io run its configured enter action.

POST

Send a geofence-enter event

Processes a geofence enter event. This is mainly used by mobile clients and location automations.

Response status: 200Operation ID: post-geofencing-enter
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/geofencing/enter' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "latitude": 52.2297,
  "longitude": 21.0122,
  "source": "ios-geofence"
}'
Request body example
{
  "latitude": 52.2297,
  "longitude": 21.0122,
  "source": "ios-geofence"
}
Response example
{
  "endedAt": null,
  "name": "geofencing test",
  "projectId": null,
  "startedAt": "2026-07-03T10:00:00.000Z"
}
/geofencing/exit

Geofence exit trigger

Signal that a device left a geofence and let Sandtime.io stop pending work where configured.

POST

Send a geofence-exit event

Processes a geofence exit event and returns the pending activities that were stopped.

Response status: 200Operation ID: post-geofencing-exit
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/geofencing/exit' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "latitude": 52.2297,
  "longitude": 21.0122,
  "source": "ios-geofence"
}'
Request body example
{
  "latitude": 52.2297,
  "longitude": 21.0122,
  "source": "ios-geofence"
}
Response example
[
  {
    "billable": true,
    "endedAt": "2026-07-03T08:30:00.000Z",
    "id": "c2dbd56f-0f09-4bf8-87ae-a1c8d7e5f302",
    "name": "Implement API docs page",
    "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "startedAt": "2026-07-03T07:00:00.000Z",
    "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d"
  }
]

Requests

Approval and assignment workflows live under /requests.

/requests/projects/{projectId}/members/{memberId}/role

Create role-change request

Create a project role-change request for a member.

Path parameters

  • projectId: The project identifier.
  • memberId: The project member identifier.
POST

Create a role-change request

Creates a request to change the selected project member role.

Response status: 200Operation ID: post-requests-projects-projectId-members-memberId-role
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/requests/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members/3b13dd8f-bc60-4db8-a2bc-5eb16ca31a04/role' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "role": "Administrator"
}'
Request body example
{
  "role": "Administrator"
}
Response example
{
  "createdAt": "2026-07-03T09:02:11.000Z",
  "createdBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "1fbbd48d-176f-4b32-a98d-c8cf1eb291c5",
  "resolvedAt": "2026-07-03T09:08:45.000Z",
  "resolvedBy": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "status": "RESOLVED",
  "projectId": "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
  "role": "Administrator"
}
/requests/{requestId}/projects/members/role

Resolve role-change request

Resolve a role-change request by marking it RESOLVED or REJECTED.

Path parameters

  • requestId: The workflow request identifier.
PUT

Resolve a role-change request

Applies or rejects the role change for an existing request.

Response status: 200Operation ID: put-requests-requestId-projects-members-role
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/requests/1fbbd48d-176f-4b32-a98d-c8cf1eb291c5/projects/members/role' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "RESOLVED"
}'
Request body example
{
  "status": "RESOLVED"
}
Response example
{
  "createdAt": "2026-07-03T09:02:11.000Z",
  "createdBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "1fbbd48d-176f-4b32-a98d-c8cf1eb291c5",
  "resolvedAt": "2026-07-03T09:08:45.000Z",
  "resolvedBy": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "status": "RESOLVED"
}
/requests/projects/{projectId}/members

Create project-member assignment request

Create a project-member assignment request.

Path parameters

  • projectId: The project identifier.
POST

Create a project-member assignment request

Creates a request to assign one or more users to a project.

Response status: 200Operation ID: post-requests-projects-projectId-members
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/requests/projects/9d58c4ce-3e6f-4d06-bf47-f70d8c4af001/members' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "userIds": [
    "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af"
  ]
}'
Request body example
{
  "userIds": [
    "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af"
  ]
}
Response example
{
  "createdAt": "2026-07-03T09:02:11.000Z",
  "createdBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "1fbbd48d-176f-4b32-a98d-c8cf1eb291c5",
  "resolvedAt": "2026-07-03T09:08:45.000Z",
  "resolvedBy": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "status": "RESOLVED"
}
/requests/{requestId}/projects/members

Resolve project-member assignment request

Resolve a project-member assignment request.

Path parameters

  • requestId: The workflow request identifier.
PUT

Resolve a project-member assignment request

Marks the request RESOLVED or REJECTED. Resolved requests assign the selected users to the project.

Response status: 200Operation ID: put-requests-requestId-projects-members
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/requests/1fbbd48d-176f-4b32-a98d-c8cf1eb291c5/projects/members' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "RESOLVED"
}'
Request body example
{
  "status": "RESOLVED"
}
Response example
{
  "createdAt": "2026-07-03T09:02:11.000Z",
  "createdBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "1fbbd48d-176f-4b32-a98d-c8cf1eb291c5",
  "resolvedAt": "2026-07-03T09:08:45.000Z",
  "resolvedBy": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "status": "RESOLVED"
}
/requests/projects/request-assignment

Create project-assignment request

Create a request for assignment to one or more projects.

POST

Create a project-assignment request

Creates a self-service request asking administrators to assign the current user to projects.

Response status: 200Operation ID: post-requests-projects-request-assignment
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/requests/projects/request-assignment' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "createdAt": "2026-07-03T09:02:11.000Z",
  "createdBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "1fbbd48d-176f-4b32-a98d-c8cf1eb291c5",
  "resolvedAt": "2026-07-03T09:08:45.000Z",
  "resolvedBy": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "status": "RESOLVED"
}
/requests/{requestId}/projects/assign

Resolve project-assignment request

Resolve a request for assignment to projects.

Path parameters

  • requestId: The workflow request identifier.
PUT

Resolve a project-assignment request

Marks the request RESOLVED or REJECTED. Resolved requests use `projectIds` to assign the requester to projects.

Response status: 200Operation ID: put-requests-requestId-projects-assign
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/requests/1fbbd48d-176f-4b32-a98d-c8cf1eb291c5/projects/assign' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "projectIds": [
    "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "58f5aa89-aed2-4a67-8808-d85ef4034f42"
  ],
  "status": "RESOLVED"
}'
Request body example
{
  "projectIds": [
    "9d58c4ce-3e6f-4d06-bf47-f70d8c4af001",
    "58f5aa89-aed2-4a67-8808-d85ef4034f42"
  ],
  "status": "RESOLVED"
}
Response example
{
  "createdAt": "2026-07-03T09:02:11.000Z",
  "createdBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "1fbbd48d-176f-4b32-a98d-c8cf1eb291c5",
  "resolvedAt": "2026-07-03T09:08:45.000Z",
  "resolvedBy": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "status": "RESOLVED"
}
/requests/{requestId}

Resolve impersonation request

Resolve an impersonation request raised elsewhere in the product.

Path parameters

  • requestId: The workflow request identifier.
PUT

Resolve an impersonation request

Marks the impersonation request RESOLVED or REJECTED. A resolved request triggers a one-time support sign-in link.

Response status: 200Operation ID: put-requests-requestId
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/requests/1fbbd48d-176f-4b32-a98d-c8cf1eb291c5' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "RESOLVED"
}'
Request body example
{
  "status": "RESOLVED"
}
Response example
{
  "createdAt": "2026-07-03T09:02:11.000Z",
  "createdBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "1fbbd48d-176f-4b32-a98d-c8cf1eb291c5",
  "resolvedAt": "2026-07-03T09:08:45.000Z",
  "resolvedBy": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "status": "RESOLVED"
}
/requests/timesheets/{year}/{week}/unlock

Create timesheet-unlock request

Create an unlock request for a locked weekly timesheet.

Path parameters

  • year: ISO week-numbering year.
  • week: ISO week number in the organization time zone.
POST

Create a timesheet-unlock request

Creates a request asking administrators to unlock one weekly timesheet.

Response status: 200Operation ID: post-requests-timesheets-year-week-unlock
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/requests/timesheets/2026/27/unlock' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "createdAt": "2026-07-03T09:02:11.000Z",
  "createdBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "1fbbd48d-176f-4b32-a98d-c8cf1eb291c5",
  "resolvedAt": "2026-07-03T09:08:45.000Z",
  "resolvedBy": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "status": "RESOLVED"
}
/requests/{requestId}/timesheets/unlock

Resolve timesheet-unlock request

Resolve a timesheet-unlock request.

Path parameters

  • requestId: The workflow request identifier.
PUT

Resolve a timesheet-unlock request

Marks the unlock request RESOLVED or REJECTED. A resolved request opens the timesheet for a temporary editing window.

Response status: 200Operation ID: put-requests-requestId-timesheets-unlock
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/requests/1fbbd48d-176f-4b32-a98d-c8cf1eb291c5/timesheets/unlock' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "RESOLVED"
}'
Request body example
{
  "status": "RESOLVED"
}
Response example
{
  "createdAt": "2026-07-03T09:02:11.000Z",
  "createdBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "1fbbd48d-176f-4b32-a98d-c8cf1eb291c5",
  "resolvedAt": "2026-07-03T09:08:45.000Z",
  "resolvedBy": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "status": "RESOLVED"
}
/requests/timesheets/{year}/{week}/approvals

Create timesheet-approval request

Create an approval request for a weekly timesheet.

Path parameters

  • year: ISO week-numbering year.
  • week: ISO week number in the organization time zone.
POST

Create a timesheet-approval request

Creates a request asking administrators to approve a weekly timesheet.

Response status: 200Operation ID: post-requests-timesheets-year-week-approvals
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/requests/timesheets/2026/27/approvals' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{
  "createdAt": "2026-07-03T09:02:11.000Z",
  "createdBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "1fbbd48d-176f-4b32-a98d-c8cf1eb291c5",
  "resolvedAt": "2026-07-03T09:08:45.000Z",
  "resolvedBy": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "status": "RESOLVED"
}
/requests/{requestId}/timesheets/approvals

Resolve timesheet-approval request

Resolve a timesheet-approval request.

Path parameters

  • requestId: The workflow request identifier.
PUT

Resolve a timesheet-approval request

Marks the approval request RESOLVED or REJECTED.

Response status: 200Operation ID: put-requests-requestId-timesheets-approvals
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/requests/1fbbd48d-176f-4b32-a98d-c8cf1eb291c5/timesheets/approvals' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "RESOLVED"
}'
Request body example
{
  "status": "RESOLVED"
}
Response example
{
  "createdAt": "2026-07-03T09:02:11.000Z",
  "createdBy": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "id": "1fbbd48d-176f-4b32-a98d-c8cf1eb291c5",
  "resolvedAt": "2026-07-03T09:08:45.000Z",
  "resolvedBy": "8eb3c82f-420d-4a7d-b4e5-689f6cf9c8af",
  "status": "RESOLVED"
}

Timesheets

Explicit timesheet locks, automatic lock execution, and reminder delivery.

/timesheets/auto-lock

Auto-lock runner

Run the organization auto-lock routine against the current time zone and lock settings.

PUT

Run auto-lock

Evaluates whether the next weekly lock should run and updates organization lock metadata when it does.

Response status: 200Operation ID: put-timesheets-auto-lock
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/timesheets/auto-lock' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "scheduled-reminder-run"
}'
Request body example
{
  "reason": "scheduled-reminder-run"
}
Response example
{
  "coreHours": {
    "end": "17:00",
    "start": "09:00"
  },
  "currency": "USD",
  "holidays": {
    "country": "US",
    "excluded": []
  },
  "id": "8a4affba-df59-47bd-8173-d175e76efd15",
  "lockingTimesheets": {
    "enabled": false,
    "timeZone": null,
    "week": null,
    "year": null
  },
  "name": "Acme Studio",
  "notes": "Weekly client delivery team.",
  "onboarding": {
    "assignMembers": {
      "done": true,
      "viewed": true
    },
    "inviteMembers": {
      "done": true,
      "viewed": true
    },
    "organization": {
      "done": true,
      "viewed": true
    },
    "preferences": {
      "done": false,
      "viewed": true
    },
    "projects": {
      "done": true,
      "viewed": true
    }
  },
  "plan": "free",
  "rounding": {
    "enabled": false,
    "interval": 900000,
    "mode": "NEAREST"
  },
  "timeZone": "Europe/Warsaw"
}
/timesheets/lock

Timesheet lock collection

Create a lock or temporary unlock window for one user and one ISO week.

POST

Create a timesheet lock

Creates or replaces one timesheet lock for the selected user/week combination.

Response status: 200Operation ID: post-timesheets-lock
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/timesheets/lock' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "unlockedTo": "2026-07-04T20:00:00+02:00",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "week": 27,
  "year": 2026
}'
Request body example
{
  "unlockedTo": "2026-07-04T20:00:00+02:00",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "week": 27,
  "year": 2026
}
Response example
{
  "createdAt": "2026-07-03T10:00:00.000Z",
  "id": "5c27ad51-cbb7-4f96-84c7-f19dd3750a42",
  "unlockedTo": "2026-07-04T18:00:00.000Z",
  "updatedAt": "2026-07-03T10:00:00.000Z",
  "userId": "2f9fd8a8-9f6d-4b2b-a4f4-1f1f2a7d9b9d",
  "week": 27,
  "year": 2026
}
/timesheets/lock/{lockId}

Single timesheet lock

Delete one explicit timesheet lock or unlock window.

Path parameters

  • lockId: The timesheet lock identifier.
DELETE

Delete a timesheet lock

Deletes one timesheet lock by ID.

Response status: 200Operation ID: delete-timesheets-lock-lockId
cURL example
curl -X DELETE 'https://your-organization.sandtime.io/api/timesheets/lock/5c27ad51-cbb7-4f96-84c7-f19dd3750a42' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
{}
/timesheets/reminder

Timesheet reminder runner

Trigger the reminder flow that asks users to fill timesheets before the automatic lock runs.

POST

Send timesheet reminders

Runs the reminder logic for the current organization.

Response status: 200Operation ID: post-timesheets-reminder
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/timesheets/reminder' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "friday-evening-check"
}'
Request body example
{
  "reason": "friday-evening-check"
}
Response example
null

Billing

Billing, plan changes, and checkout helpers.

/subscriptions

Subscription collection

Read the current subscription collection for the organization.

GET

List subscriptions

Returns subscription records for the current organization.

Response status: 200Operation ID: get-subscriptions
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/subscriptions' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
[
  {
    "id": "sub_01J1YB3TQK5K9S2H4E5T6U7V8W",
    "nextBillDate": "2026-08-01",
    "plan": "monthly",
    "quantity": 1,
    "status": "active"
  }
]
/subscriptions/{subscriptionId}

Single subscription

Update one subscription, usually to change quantity or payment state.

Path parameters

  • subscriptionId: The external subscription identifier.
PUT

Update a subscription

Updates one existing subscription. This route is limited to administrators.

Response status: 200Operation ID: put-subscriptions-subscriptionId
cURL example
curl -X PUT 'https://your-organization.sandtime.io/api/subscriptions/sub_01J1YB3TQK5K9S2H4E5T6U7V8W' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "quantity": 2
}'
Request body example
{
  "quantity": 2
}
Response example
{}
/checkout

Checkout

Create a checkout link for a plan change.

POST

Create a checkout link

Creates a Paddle checkout link for the selected product and quantity.

Response status: 200Operation ID: post-checkout
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/checkout' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "product": 123456,
  "quantity": 1
}'
Request body example
{
  "product": 123456,
  "quantity": 1
}
Response example
{
  "url": "https://pay.paddle.com/pay/cpl_example"
}
/billing-history

Billing history

Read the billing transaction history for the current organization.

GET

List billing history

Returns the current billing history from the payment provider.

Response status: 200Operation ID: get-billing-history
cURL example
curl -X GET 'https://your-organization.sandtime.io/api/billing-history' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json"
Response example
[
  {
    "amount": 4900,
    "currency": "USD",
    "id": "txn_01J1YB6A0M2K8H5V7P9R4S3T2Q",
    "paidAt": "2026-07-01T08:10:00.000Z",
    "status": "paid"
  }
]
/receipt

Receipt upload

Upload an App Store receipt for validation.

POST

Upload a receipt

Submits a base64-encoded receipt payload to the billing backend.

Response status: 200Operation ID: post-receipt
cURL example
curl -X POST 'https://your-organization.sandtime.io/api/receipt' \
  -H "Authorization: Bearer YOUR_SANDTIME_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "receiptBase64": "MIIT9QYJKoZIhvcNAQcCoIIT5jCCE+ICAQExCzAJBgUr..."
}'
Request body example
{
  "receiptBase64": "MIIT9QYJKoZIhvcNAQcCoIIT5jCCE+ICAQExCzAJBgUr..."
}
Response example
{
  "ok": true
}