v4 REST API

The v4 REST API is plain HTTPS over JSON. Every route lives under https://ai.growrk.com/v4 and is authenticated with a user-bound API key.

Authentication

Send your key (prefix grk_sk_) in the X-API-KEY header on every request:

curl https://ai.growrk.com/v4/me \
  -H "X-API-KEY: grk_sk_your_key_here"

A missing or invalid key returns 401 Unauthorized. See Authentication & API keys to mint one and choose its capabilities.

Postman collection

Rather than building requests by hand, import the ready-made collection:

Download the GroWrk v4 Client API collection (Postman Collection v2.1.0, 27 requests across 8 folders).

In Postman, choose File → Import and drop the file in. No Postman account or workspace access is needed.

It arrives already wired up:

  • Authentication is set at the collection level to the X-API-KEY header, reading a collection variable. Paste your grk_sk_ key into the apiKey variable once and every request inherits it.
  • baseUrl is a variable too (https://ai.growrk.com), so you can point the whole collection at another environment by editing one value.
  • Each request documents the capability it needs, so a 403 tells you which scope to add to your key.

The collection is generated from the same route table and tool schemas that back the API itself, so it cannot drift out of sync with the endpoints documented below.

Resources

ResourceEndpoints
OrdersGET /v4/orders · GET /v4/orders/{id} · POST /v4/orders · POST /v4/orders/purchase · GET /v4/orders/{id}/history · GET /v4/orders/{id}/tracking · GET /v4/orders/{id}/sla · POST /v4/orders/validate · POST /v4/orders/{id}/accessories
EmployeesGET /v4/employees · GET /v4/employees/{id} · POST /v4/employees · PATCH /v4/employees/{id} · GET /v4/employees/{id}/devices · GET /v4/employees/countries
TeamsGET /v4/teams · GET /v4/teams/{id} · POST /v4/teams · PATCH /v4/teams/{id}
Inventory / devicesGET /v4/inventory · GET /v4/devices/options · GET /v4/devices/suggestions
ProductsGET /v4/products/{id} · POST /v4/products/pin-code
CompanyGET /v4/company/addresses · POST /v4/company/addresses
IdentityGET /v4/me

Each write endpoint requires the matching capability on your key (mcp:orders:write, mcp:employees:write); read endpoints require the matching read capability. GET /v4/me needs no scope.

Two endpoints do not follow the obvious mapping:

  • POST /v4/orders/validate is a POST but is read-only: it requires mcp:orders:read, not :write.
  • GET /v4/employees/{id}/devices sits under Employees but requires mcp:inventory:read, not mcp:employees:read.

Lists: pagination & filtering

GET /v4/orders and GET /v4/employees accept these query parameters:

ParameterApplies toDescription
queryorders, employeesFree-text search
emailemployeesExact email match (case-insensitive). An equality filter, not a search. Use it to resolve one known employee
statusorders, employeesFilter by status (orders accept multiple status values)
typeordersFilter by order type (multiple allowed)
countryemployeesFilter by country (ISO 3166-1 alpha-2, e.g. US, BR)
pageorders, employeesPage number, 0-indexed, default 0
limitorders, employeesPage size, default 20, maximum 50
sortorders, employeesField to sort by
sortDirectionorders, employeesasc or desc (default: desc for orders, asc for employees)

There is no "return everything" mode. limit is capped at 50, so page through large result sets with page.

GET /v4/inventory filters with query, category, country, status, inStock, and limit (default 20, max 50). GET /v4/devices/options caps limit at 25 (default 10) and GET /v4/devices/suggestions at 15 (default 5). Repeat a parameter to pass multiple values, e.g. ?status=shipped&status=delivered.

Response format

On success the API returns the operation's result as a JSON object. Read operations return the resource payload; most results carry a status: "success" field alongside the data. For example, GET /v4/me:

{
  "authenticated": true,
  "user": {
    "uid": "usr_1a2b3c",
    "email": "jane@example.com",
    "displayName": "Jane Doe"
  },
  "access": {
    "isStaff": false,
    "isDeveloper": true,
    "companyIds": ["co_acme"],
    "supplierIds": []
  }
}

And a list, GET /v4/orders:

{
  "status": "success",
  "orders": [
    { "id": "ord_123", "status": "shipped", "type": "Deployment" }
  ]
}

The growrk CLI (and other GroWrk clients) wrap this result in a unified envelope, { ok, data, meta }, so scripts can branch on ok and read a correlation id from meta. The raw REST response is the inner data; see CLI output formats.

Error codes

Failures return the matching HTTP status with a JSON body containing statusCode and statusMessage:

{ "statusCode": 404, "statusMessage": "Order ord_123 not found" }
StatusMeaning
400 Bad RequestInvalid input: a missing or malformed field
401 UnauthorizedMissing X-API-KEY header, or a key that is invalid, inactive, expired, unauthorized, or bound to a user who has been disabled or deleted. A legacy GW. v2 key also lands here
403 ForbiddenYour key lacks the required capability, or the record is outside your scope
404 Not FoundThe requested resource does not exist (or is not visible to you)
409 ConflictThe request conflicts with existing state (e.g. a duplicate employee email)
500 Internal Server ErrorAn unexpected failure. The body is always the generic "Request failed"; the underlying error is deliberately not returned, only logged server-side. Report the endpoint and the time of the request

Examples

All examples below are copy-pasteable. Replace grk_sk_your_key_here and the sample ids with your own.

Identity

curl https://ai.growrk.com/v4/me \
  -H "X-API-KEY: grk_sk_your_key_here"

Orders

# List the 10 most recent shipped orders
curl "https://ai.growrk.com/v4/orders?status=shipped&limit=10" \
  -H "X-API-KEY: grk_sk_your_key_here"

# Get one order
curl https://ai.growrk.com/v4/orders/ord_123 \
  -H "X-API-KEY: grk_sk_your_key_here"

# Order history, tracking, and SLA
curl https://ai.growrk.com/v4/orders/ord_123/history  -H "X-API-KEY: grk_sk_your_key_here"
curl https://ai.growrk.com/v4/orders/ord_123/tracking -H "X-API-KEY: grk_sk_your_key_here"
curl https://ai.growrk.com/v4/orders/ord_123/sla      -H "X-API-KEY: grk_sk_your_key_here"

# Pre-flight validation (read-only) before placing an order
curl -X POST https://ai.growrk.com/v4/orders/validate \
  -H "X-API-KEY: grk_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"orderType":"Deployment","employeeId":"emp_123","productIds":["prod_456"]}'

# Place a deployment order (requires mcp:orders:write)
curl -X POST https://ai.growrk.com/v4/orders \
  -H "X-API-KEY: grk_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"orderType":"Deployment","employeeId":"emp_123","productIds":["prod_456"]}'

# Request a replacement charger for a device on an existing order.
# `productId` identifies the DEVICE that needs the charger, not a charger SKU.
# Only devices whose charger status is "Damaged" or "Not Included" are eligible.
curl -X POST https://ai.growrk.com/v4/orders/ord_123/accessories \
  -H "X-API-KEY: grk_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"productId":"prod_456"}'

# The device can also be identified by serial number instead of productId
curl -X POST https://ai.growrk.com/v4/orders/ord_123/accessories \
  -H "X-API-KEY: grk_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"serialNumber":"C02XY1234ABC"}'

# Purchase from the GroWrk catalog (requires mcp:orders:write).
# `itemId` is a catalog item id, NOT a legacy v2 companyItem id, and each
# item carries the country it ships from, because quotes are per region.
# Use "Purchase for Inventory" to stock the company pool instead of an employee.
curl -X POST https://ai.growrk.com/v4/orders/purchase \
  -H "X-API-KEY: grk_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "orderType": "Purchase for Employee",
    "employeeId": "emp_123",
    "items": [{ "itemId": "item_789", "quantity": 1, "country": "US" }],
    "shippingType": "standard"
  }'

Configure / build-to-order devices cannot be bought this way. Use a custom request for those.

Employees

# List employees
curl "https://ai.growrk.com/v4/employees?query=jane&limit=20" \
  -H "X-API-KEY: grk_sk_your_key_here"

# Get one employee
curl https://ai.growrk.com/v4/employees/emp_123 \
  -H "X-API-KEY: grk_sk_your_key_here"

# Devices assigned to an employee
curl https://ai.growrk.com/v4/employees/emp_123/devices \
  -H "X-API-KEY: grk_sk_your_key_here"

# Create an employee (requires mcp:employees:write)
curl -X POST https://ai.growrk.com/v4/employees \
  -H "X-API-KEY: grk_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"displayName":"Jane Doe","email":"jane@example.com","country":"US"}'

# Update an employee's job title (requires mcp:employees:write)
curl -X PATCH https://ai.growrk.com/v4/employees/emp_123 \
  -H "X-API-KEY: grk_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"jobTitle":"Staff Engineer"}'

# Countries you already have employees in, derived from their stored delivery
# addresses. Returns each region as { value, label }, useful for populating a
# country picker before placing an order.
curl https://ai.growrk.com/v4/employees/countries \
  -H "X-API-KEY: grk_sk_your_key_here"

Employee updates are restricted to a whitelist of editable fields: status, offboarding, payroll and identity fields are not writable through the API. Address changes affect future orders only, because the delivery address is read when an order is created.

Inventory & devices

# Search company inventory
curl "https://ai.growrk.com/v4/inventory?query=macbook&inStock=true&country=US" \
  -H "X-API-KEY: grk_sk_your_key_here"

# Device options for ordering. `location` is where the device sits, one of
# "GroWrk Warehouse", "Employee Address", "Client Location", "In transit",
# not a country. Add `specs` to bias the ranking.
curl "https://ai.growrk.com/v4/devices/options?productType=Laptop&location=GroWrk%20Warehouse&specs=16GB%20512GB" \
  -H "X-API-KEY: grk_sk_your_key_here"

# Alternative-device suggestions for a country
curl "https://ai.growrk.com/v4/devices/suggestions?country=DE&productType=Laptop" \
  -H "X-API-KEY: grk_sk_your_key_here"

Products

# One inventory product (device): assignment, condition, location, serial
curl https://ai.growrk.com/v4/products/prod_456 \
  -H "X-API-KEY: grk_sk_your_key_here"

# Store a device unlock PIN (requires mcp:inventory:write).
# Identify the device by productId OR serialNumber. Only device types that
# support a PIN are eligible: Desktops, Laptops, Mobile, Tablet.
curl -X POST https://ai.growrk.com/v4/products/pin-code \
  -H "X-API-KEY: grk_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"productId":"prod_456","pinCode":"482913"}'

Employees may only read their own devices.

Teams

# List teams (managers see only the teams their role scopes them to)
curl https://ai.growrk.com/v4/teams \
  -H "X-API-KEY: grk_sk_your_key_here"

# One team, including its employee count
curl https://ai.growrk.com/v4/teams/team_321 \
  -H "X-API-KEY: grk_sk_your_key_here"

# Create a team (requires mcp:teams:write)
curl -X POST https://ai.growrk.com/v4/teams \
  -H "X-API-KEY: grk_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"name":"Platform Engineering"}'

# Rename a team (requires mcp:teams:write)
curl -X PATCH https://ai.growrk.com/v4/teams/team_321 \
  -H "X-API-KEY: grk_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"name":"Core Platform"}'

Team names must be unique within the company, because the employee endpoints resolve teams by name and a duplicate would make that lookup ambiguous. Creating or renaming to an existing name returns 409 Conflict.

Company addresses

# Saved office / warehouse locations devices can ship to or be collected from
curl https://ai.growrk.com/v4/company/addresses \
  -H "X-API-KEY: grk_sk_your_key_here"

# Save a new address (requires mcp:company:write)
curl -X POST https://ai.growrk.com/v4/company/addresses \
  -H "X-API-KEY: grk_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "alias": "Madrid office",
    "address": "Calle de Alcalá 45",
    "city": "Madrid",
    "zipCode": "28014",
    "country": "ES",
    "contactName": "Ana García",
    "contactEmail": "ana@example.com",
    "phone": "+34600000000"
  }'

country must exist in the GroWrk regional catalog; addressTwo and state are optional, the rest are required.

Prefer a terminal or an AI assistant? The same operations are available through the CLI and MCP.