TabHR API

Programmatically manage your virtual employees, their containers, tasks, chat, accounts, and more.

Base URL

http://tabhr.com/api/v1

Auth

Bearer token via API key

Format

JSON request/response

Interactive OpenAPI explorer with try-it-out: /api-docs/openapi · openapi.json

Quick Start

  1. 1Go to Settings and generate an API key
  2. 2Add the key to your Authorization: Bearer tabhr_... header
  3. 3Make requests to any endpoint below
# List your employees
curl -s "http://tabhr.com/api/v1/employees" \
  -H "Authorization: Bearer tabhr_YOUR_KEY" | jq

Authentication

All API requests require a valid API key passed in the Authorization header.

Header Format

Authorization: Bearer tabhr_YOUR_API_KEY

Managing Keys

  • Generate API keys in Settings → API Keys
  • Keys can be revoked at any time — revoked keys immediately stop working
  • API key secrets are shown once at creation — store them securely
  • Maximum 25 active keys per account

Permissions & scoping

Each key can be limited to specific permissions and specific employees. A request that exceeds the key's permissions returns 403; an employee outside the key's allow-list returns 404.

  • Full access (default) — every permission across all employees
  • Permissions — granular grants like employees:read, tasks:write, containers:write
  • Employee access — restrict a key to one or more specific employees

Employees

Create, list, update, and delete virtual employees.

Containers

Deploy, stop, redeploy, and terminate employee containers.

Chat

Send messages to employees and retrieve chat history.

Tasks

Assign, update, and manage tasks for employees.

Contacts & Accounts

Manage contact methods and linked accounts (email, phone, Slack, etc.).

Action Logs

Retrieve activity and action logs for employees.

Real-time chat (WebSocket)

Open a WebSocket to stream a conversation with an employee's agent in real time — you receive the agent's thinking, token-by-token streaming, and the final message as they happen. Messages sent over HTTP (POST .../chat) are broadcast to connected sockets too, so you can post over HTTP and listen here.

Endpoint

ws://tabhr.com/api/v1/employees/{employeeId}/chat/ws?api_key=tabhr_YOUR_KEY

Authenticate with the api_key query parameter, or an Authorization: Bearer header if your client supports it. Requires the chat:read permission to connect and chat:write to send.

Send a message

{ "type": "send", "content": "What's the status of the Q3 report?" }

Events you receive

  • connected — handshake ack with canWrite
  • message — a persisted user or employee message
  • thinking — agent reasoning / tool-use status
  • streaming — incremental reply text (delta + full text)
  • stream_end — the reply is complete
  • error — delivery or agent error

Example (Node)

import WebSocket from "ws";

const ws = new WebSocket(
  "ws://tabhr.com/api/v1/employees/EMPLOYEE_ID/chat/ws?api_key=tabhr_YOUR_KEY"
);

ws.on("message", (raw) => {
  const evt = JSON.parse(raw.toString());
  if (evt.type === "streaming") process.stdout.write(evt.delta);
  if (evt.type === "message" && evt.message.sender === "EMPLOYEE") {
    console.log("\nReply:", evt.message.content);
  }
});

ws.on("open", () => {
  ws.send(JSON.stringify({ type: "send", content: "Hello!" }));
});

Post over HTTP, wait for the reply

# Block until the agent replies and return it inline
curl -X POST "http://tabhr.com/api/v1/employees/EMPLOYEE_ID/chat?wait=true" \
  -H "Authorization: Bearer tabhr_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content":"Summarize today\'s tasks"}'

Errors

The API uses standard HTTP status codes and returns JSON error bodies.

StatusMeaning
400Bad Request — Invalid parameters or missing required fields
401Unauthorized — Missing or invalid API key
402Payment Required — Billing setup needed before deploying
403Forbidden — Operation not allowed
404Not Found — Resource doesn't exist or doesn't belong to you
409Conflict — Resource already in the requested state
500Server Error — Something went wrong on our end

Error Response Format

{
  "error": "Human-readable error message"
}

Rate Limits

The API currently has generous rate limits. If you encounter 429 responses, back off and retry with exponential backoff. We reserve the right to rate-limit abusive usage patterns.