Admin API

Scripts

Manage trigger-keyed scripts. Scripts run automatically in response to events like record indexing, XRPC calls, or labeler actions. The trigger id (e.g. record.index:xyz.statusphere.status) determines when a script fires.

Permissions: scripts:read for GET endpoints, scripts:manage for mutating endpoints.

const TOKEN = "hv_..."; // your API key
const headers = { Authorization: `Bearer ${TOKEN}` };

List scripts

GET /admin/scripts

Optionally filter by NSID suffix with the ?suffix= query parameter.

interface Script {
  id: string;
  script_type: string;
  body: string;
  description: string | null;
  created_at: string;
  updated_at: string;
}

// List all scripts
const response = await fetch("http://127.0.0.1:3000/admin/scripts", {
  headers,
});
const data: Script[] = await response.json();

// Filter by NSID suffix
const filtered = await fetch(
  "http://127.0.0.1:3000/admin/scripts?suffix=xyz.statusphere.status",
  { headers },
);
const filteredData: Script[] = await filtered.json();
ParameterTypeRequiredDescription
suffixstringnoFilter to scripts whose id ends with :<suffix> (query param)

Response: 200 OK

[
  {
    "id": "record.index:xyz.statusphere.status",
    "script_type": "lua",
    "body": "function handle()\n  return event\nend",
    "description": "Process indexed statuses",
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-01T00:00:00Z"
  }
]

Get a script

GET /admin/scripts/{id}

The {id} path parameter is the trigger string, URL-encoded (e.g. record.index%3Axyz.statusphere.status).

const response = await fetch(
  "http://127.0.0.1:3000/admin/scripts/record.index%3Axyz.statusphere.status",
  { headers },
);
const data: Script = await response.json();

Response: 200 OK

{
  "id": "record.index:xyz.statusphere.status",
  "script_type": "lua",
  "body": "function handle()\n  return event\nend",
  "description": "Process indexed statuses",
  "created_at": "2026-01-01T00:00:00Z",
  "updated_at": "2026-01-01T00:00:00Z"
}

Create or replace a script

POST /admin/scripts

Creates a new script or replaces an existing one by id. The trigger grammar and Lua body are validated at write-time.

const response = await fetch("http://127.0.0.1:3000/admin/scripts", {
  method: "POST",
  headers: {
    ...headers,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    id: "record.index:xyz.statusphere.status",
    script_type: "lua",
    body: "function handle()\n  return event\nend",
    description: "Process indexed statuses",
  }),
});
const data: Script = await response.json();
FieldTypeRequiredDescription
idstringyesTrigger string (e.g. record.index:xyz.statusphere.status)
script_typestringnoScript language; defaults to "lua"
bodystringyesThe script source code
descriptionstringnoHuman-readable description (max 300 characters)

Response: 201 Created (new) or 200 OK (update)

{
  "id": "record.index:xyz.statusphere.status",
  "script_type": "lua",
  "body": "function handle()\n  return event\nend",
  "description": "Process indexed statuses",
  "created_at": "2026-01-01T00:00:00Z",
  "updated_at": "2026-01-01T00:00:00Z"
}

Partial update a script

PATCH /admin/scripts/{id}

Updates individual fields of an existing script. At least one field must be provided. Setting description to null in JSON clears it. If script_type is changed, body must also be provided so validation can run against the new type.

const response = await fetch(
  "http://127.0.0.1:3000/admin/scripts/record.index%3Axyz.statusphere.status",
  {
    method: "PATCH",
    headers: {
      ...headers,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      description: "Updated description for status processing",
    }),
  },
);
const data: Script = await response.json();
FieldTypeRequiredDescription
script_typestringnoScript language; requires body alongside
bodystringnoNew script source; re-validated against script_type
descriptionstring|nullnoNew description, or null to clear

Response: 200 OK

{
  "id": "record.index:xyz.statusphere.status",
  "script_type": "lua",
  "body": "function handle()\n  return event\nend",
  "description": "Updated description for status processing",
  "created_at": "2026-01-01T00:00:00Z",
  "updated_at": "2026-01-01T00:00:00Z"
}

Delete a script

DELETE /admin/scripts/{id}
const response = await fetch(
  "http://127.0.0.1:3000/admin/scripts/record.index%3Axyz.statusphere.status",
  {
    method: "DELETE",
    headers,
  },
);

Response: 204 No Content