Skip to content
TruTecDevelopers
Get an API key

Users & workspace

Read the workspace profile, plan and products, team members with their roles and teams, and invite new members by email.

View as Markdown

A workspace is one company in TruTec. Every API key belongs to one workspace and sees only its data. These endpoints describe the workspace and the people in it, so your system can show the right company details, map TruTec user ids to your own staff records and onboard new members.

Billing is not available through the API: you can read the plan's name, but never payment details, and nothing here changes the plan.

To change the company profile, branding, estimating defaults, sales tax, job numbering and the other workspace settings, see Settings.

Note

Partner keys add firm_id to name the workspace: in the query string, or in the JSON body on writes. See Partner API.

Workspace#

Get the workspace#

GET /v1/workspace

Permission: Read jobs

curl https://trutec.ai/api/v1/workspace \
  -H "X-API-Key: sk_your_api_key_here"
{
  "data": {
    "id": 77,
    "name": "Northgate Paving",
    "plan": {"code": "gold", "name": "Gold"},
    "subscription_status": "active",
    "timezone": "America/Chicago",
    "address": "2200 Yard Rd, Austin, TX 78744",
    "website": "https://northgatepaving.example",
    "branding": {
      "logo_url": "https://media.example.com/logos/northgate.png?expires=1760285051&signature=...",
      "share_subdomain": "northgate"
    },
    "products": {
      "bid": true,
      "build": true,
      "aerial_takeoffs": true,
      "blueprint_takeoffs": true,
      "nearmap_imagery": true,
      "api": true,
      "landscape": false
    },
    "integrations": {"quickbooks": true, "hubspot": false, "jobber": false},
    "member_count": 14,
    "created_at": "2025-03-02T16:20:00Z"
  }
}
Field Description
plan code and display name of the plan that sets the workspace's features.
subscription_status trialing, active, past_due, canceled or pending.
timezone IANA name. Schedules, timesheets and "today" are computed in it.
address The office or yard address TruTec measures drive times from. null if not set.
website The company website shown on map exports.
branding.logo_url A time-limited link to the logo on proposals and exports. Download it rather than storing the link.
branding.share_subdomain The custom subdomain on shared links, if set.
products.bid Sales: CRM, takeoffs, estimating, proposals. Always on.
products.build Operations: schedule and dispatch, crews, the crew app, timesheets, job costing.
products.blueprint_takeoffs, nearmap_imagery, api Features the plan includes.
products.landscape The workspace measures landscaping (lawn, beds, trees) instead of paving.
integrations Which accounting and CRM connections are on.

Users#

List users#

GET /v1/users

Permission: Any active key

The workspace's team members. See List users for the parameters and response.

Get a user#

GET /v1/users/{user_id}

Permission: Read jobs

One team member with their role in this workspace and their teams.

curl https://trutec.ai/api/v1/users/311 \
  -H "X-API-Key: sk_your_api_key_here"
{
  "data": {
    "id": 311,
    "name": "Dana Ortiz",
    "username": "dana",
    "email": "[email protected]",
    "role": "member",
    "job_title": "Estimator",
    "phone_number": "+15125550142",
    "headshot_url": null,
    "is_firm_owner": false,
    "created_at": "2025-03-04T15:00:12.000000",
    "workspace_role": "member",
    "role_label": "Ops Manager",
    "custom_role": {"id": 6, "name": "Ops Manager"},
    "teams": [{"id": 3, "name": "North Crew"}],
    "active": true
  }
}
Field Description
workspace_role owner, member or crew in this workspace.
role_label What TruTec shows: Owner, Member, Crew, or the company role's name.
custom_role The company-defined role the member holds, or null.
teams Teams the person is on.
active false when the person's access is suspended.

A user who is not in this workspace returns 404 User not found.

List roles#

GET /v1/roles

Permission: Read jobs

The built-in roles and the roles the company defined in Settings › Team › Roles, with what each company role is allowed to do and how many people hold it. Built-in roles have permissions: null: Owners can do everything, Members have the standard office access, Crew use the crew app only.

{
  "data": [
    {"id": null, "key": "owner", "name": "Owner", "description": "Everything, always — billing, settings and everyone’s roles.", "built_in": true, "permissions": null, "member_count": 2},
    {"id": null, "key": "member", "name": "Member", "description": "Today’s office access. The per-person switches on Members still apply.", "built_in": true, "permissions": null, "member_count": 9},
    {"id": null, "key": "crew", "name": "Crew", "description": "The crew app only: their own work, time, photos and notes.", "built_in": true, "permissions": null, "member_count": 3},
    {"id": 6, "key": null, "name": "Ops Manager", "description": "Runs the schedule", "built_in": false,
     "permissions": [{"key": "view_pricing", "label": "See prices and costs", "group": "money"}], "member_count": 3}
  ]
}

Roles are assigned in TruTec, not through the API.

List teams#

GET /v1/teams

Permission: Read jobs

Teams are named groups of people (for example branches or crews) that jobs can be filed under: a job's team_id.

{
  "data": [
    {"id": 3, "name": "North Crew", "color": "#2563eb", "members": [{"user_id": 311, "role": "lead"}], "created_at": "2026-02-01T14:00:00Z"}
  ]
}

Invitations#

Invite a user#

POST /v1/users/invite

Permission: Write jobs, with a key created by a workspace owner

Warning

This sends an email. TruTec emails the address an invitation to join the workspace, from the same flow as Settings › Members › Invite. The link expires in 7 days.

Name Type Required Description
email string Yes Who to invite.
role string No member (the only value accepted). Owners are invited in TruTec.
curl -X POST https://trutec.ai/api/v1/users/invite \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]"}'

Returns 201:

{
  "data": {
    "id": 418,
    "email": "[email protected]",
    "role": "member",
    "status": "pending",
    "invited_by": {"id": 9, "name": "Chris Lane"},
    "expires_at": "2026-10-19T15:04:11Z",
    "accepted_at": null,
    "created_at": "2026-10-12T15:04:11Z"
  },
  "created": true
}

Inviting an email that already has a pending invitation sends a fresh link and returns 200 with "created": false. The person joins when they sign up from the link; they then appear in List users.

Status error
400 A valid email address is required, role must be member, Unknown fields
403 Owner key required: the key was not created by an owner of this workspace
409 Already a member, with the member's user_id

List invitations#

GET /v1/invites

Permission: Read jobs

Invitations, newest first, in the shape above. Filter with status (pending, accepted, revoked, expired); page with limit and offset. An invitation whose link ran out before it was used is returned with status expired.

Revoke an invitation#

DELETE /v1/invites/{invite_id}

Permission: Write jobs and Delete records, with a key created by a workspace owner

Revokes a pending invitation; its link stops working. Returns 204. 409 Only pending invites can be revoked for accepted ones.