Skip to content

Service Actors

Service actors are non-human entities used for automated systems. They are created using API keys and used with token exchange to access data.

Base URL

All API endpoints use the following base URL:

BASE_URL = "https://api.fermi.dev/public/v1/identity"

Examples in this documentation use the full URL for clarity, but you should use the base URL in your code.

What are Service Actors?

Service actors are:

  • Non-human actors for automated systems
  • Scoped by capabilities (permissions)
  • Organization-scoped - belong to a specific organization

Creating Service Actors

Prerequisites

To create a service actor, you need:

  • An API key with provision:service:create scope
  • The organization ID where the service actor will be created

Creating via API

curl -X POST https://api.fermi.dev/public/v1/identity/service-actors \
  -H "Authorization: Bearer fmk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CI/CD Pipeline Actor",
    "organisationId": "507f1f77bcf86cd799439011",
    "capabilities": ["analytics:query", "analytics:write"],
    "status": "active"
  }'

Request Parameters:

Parameter Type Required Description
name string Yes Descriptive name for the service actor
organisationId string Yes ID of the organization this actor belongs to
capabilities string[] No Array of scopes/capabilities (default: empty)
status enum No active or suspended (default: active)

Response:

{
  "success": true,
  "message": "Service actor created successfully",
  "data": {
    "id": "6960f3d6a4d1ed0d90654714",
    "name": "CI/CD Pipeline Actor",
    "organisation": {
      "id": "6960f37ba4d1ed0d90654702",
      "capabilities": [],
      "status": "active"
    },
    "parentOrganisation": {
      "id": "68ffc9de7c7e746b83120aa7",
      "capabilities": [],
      "status": "active"
    },
    "creatorUserId": "68ffc7a57c7e746b83120a9a",
    "capabilities": ["provision:service:create", "provision:token:exchange"],
    "status": "active",
    "createdAt": "2026-01-09T12:25:58.694Z",
    "updatedAt": "2026-01-09T12:25:58.694Z"
  }
}

Response Fields:

Field Type Description
success boolean Indicates if the operation was successful
message string Human-readable message about the operation
data object The created service actor object
data.id string Unique identifier for the service actor
data.name string Name of the service actor
data.organisation object Organisation object (child org) that this service actor belongs to
data.organisation.id string Unique identifier for the child organisation
data.organisation.capabilities string[] Capabilities available to the child organisation
data.organisation.status string Status of the child organisation: "active" or "suspended"
data.parentOrganisation object Organisation object (parent org) that created this service actor
data.parentOrganisation.id string Unique identifier for the parent organisation
data.parentOrganisation.capabilities string[] Capabilities available to the parent organisation
data.parentOrganisation.status string Status of the parent organisation: "active" or "suspended"
data.capabilities string[] Array of scopes/capabilities granted to this service actor
data.status string Status of the service actor: "active" or "suspended"
data.creatorUserId string ID of the user who created this service actor
data.createdAt string ISO 8601 timestamp when the service actor was created
data.updatedAt string ISO 8601 timestamp when the service actor was last updated

Managing Service Actors

List Service Actors

List all service actors for your organization:

curl -X GET "https://api.fermi.dev/public/v1/identity/service-actors?page=1&limit=10" \
  -H "Authorization: Bearer fmk_live_your_api_key_here"

Query Parameters:

Parameter Type Required Description
page number No Page number (default: 1)
limit number No Items per page, max 50 (default: 10)

Response:

{
  "data": [
    {
      "id": "507f1f77bcf86cd799439011",
      "name": "CI/CD Pipeline Actor",
      "organisation": {
        "id": "507f1f77bcf86cd799439011",
        "capabilities": [],
        "status": "active"
      },
      "parentOrganisation": {
        "id": "507f1f77bcf86cd799439012",
        "capabilities": [],
        "status": "active"
      },
      "capabilities": ["analytics:query", "analytics:write"],
      "status": "active",
      "creatorUserId": "507f1f77bcf86cd799439013",
      "createdAt": "2025-01-01T00:00:00Z",
      "updatedAt": "2025-01-01T00:00:00Z"
    }
  ],
  "hasNextPage": false,
  "hasPreviousPage": false
}

Response Fields:

Field Type Description
data array Array of service actor objects
hasNextPage boolean Indicates if there are more pages available
hasPreviousPage boolean Indicates if there are previous pages available

Each item in the data array contains:

Field Type Description
id string Unique identifier for the service actor
name string Name of the service actor
organisation object Organisation object (child org) that this service actor belongs to
organisation.id string Unique identifier for the child organisation
organisation.capabilities string[] Capabilities available to the child organisation
organisation.status string Status of the child organisation: "active" or "suspended"
parentOrganisation object Organisation object (parent org) that created this service actor
parentOrganisation.id string Unique identifier for the parent organisation
parentOrganisation.capabilities string[] Capabilities available to the parent organisation
parentOrganisation.status string Status of the parent organisation: "active" or "suspended"
capabilities string[] Array of scopes/capabilities granted to this service actor
status string Status of the service actor: "active" or "suspended"
creatorUserId string ID of the user who created this service actor
createdAt string ISO 8601 timestamp when the service actor was created
updatedAt string ISO 8601 timestamp when the service actor was last updated

Get Service Actor by ID

curl -X GET https://api.fermi.dev/public/v1/identity/service-actors/{service-actor-id} \
  -H "Authorization: Bearer fmk_live_your_api_key_here"

Response:

{
  "id": "6960f3d6a4d1ed0d90654714",
  "name": "CI/CD Pipeline Actor",
  "organisation": {
    "id": "6960f37ba4d1ed0d90654702",
    "capabilities": [],
    "status": "active"
  },
  "parentOrganisation": {
    "id": "68ffc9de7c7e746b83120aa7",
    "capabilities": [],
    "status": "active"
  },
  "creatorUserId": "68ffc7a57c7e746b83120a9a",
  "capabilities": ["analytics:query", "analytics:write"],
  "status": "active",
  "createdAt": "2026-01-09T12:25:58.694Z",
  "updatedAt": "2026-01-09T12:25:58.694Z"
}

Response Fields:

Field Type Description
id string Unique identifier for the service actor
name string Name of the service actor
organisation object Organisation object (child org) that this service actor belongs to
organisation.id string Unique identifier for the child organisation
organisation.capabilities string[] Capabilities available to the child organisation
organisation.status string Status of the child organisation: "active" or "suspended"
parentOrganisation object Organisation object (parent org) that created this service actor
parentOrganisation.id string Unique identifier for the parent organisation
parentOrganisation.capabilities string[] Capabilities available to the parent organisation
parentOrganisation.status string Status of the parent organisation: "active" or "suspended"
capabilities string[] Array of scopes/capabilities granted to this service actor
status string Status of the service actor: "active" or "suspended"
creatorUserId string ID of the user who created this service actor
createdAt string ISO 8601 timestamp when the service actor was created
updatedAt string ISO 8601 timestamp when the service actor was last updated

Note: Returns null if the service actor is not found.

Update Service Actor

Update a service actor's name, capabilities, or status:

curl -X PATCH https://api.fermi.dev/public/v1/identity/service-actors/{service-actor-id} \
  -H "Authorization: Bearer fmk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Actor Name",
    "capabilities": ["analytics:query", "analytics:read", "analytics:write"],
    "status": "active"
  }'

Request Parameters:

Parameter Type Required Description
name string No Updated name for the service actor
capabilities string[] No Updated array of scopes/capabilities
status enum No active or suspended

Response:

{
  "success": true,
  "message": "Service actor updated successfully",
  "data": {
    "id": "6960f3d6a4d1ed0d90654714",
    "name": "Updated Actor Name",
    "organisation": {
      "id": "6960f37ba4d1ed0d90654702",
      "capabilities": [],
      "status": "active"
    },
    "parentOrganisation": {
      "id": "68ffc9de7c7e746b83120aa7",
      "capabilities": [],
      "status": "active"
    },
    "creatorUserId": "68ffc7a57c7e746b83120a9a",
    "capabilities": ["analytics:query", "analytics:read", "analytics:write"],
    "status": "active",
    "createdAt": "2026-01-09T12:25:58.694Z",
    "updatedAt": "2026-01-20T12:00:00.000Z"
  }
}

Response Fields:

Field Type Description
success boolean Indicates if the operation was successful
message string Human-readable message about the operation
data object The updated service actor object
data.id string Unique identifier for the service actor
data.name string Updated name of the service actor
data.organisation object Organisation object (child org) that this service actor belongs to
data.organisation.id string Unique identifier for the child organisation
data.organisation.capabilities string[] Capabilities available to the child organisation
data.organisation.status string Status of the child organisation: "active" or "suspended"
data.parentOrganisation object Organisation object (parent org) that created this service actor
data.parentOrganisation.id string Unique identifier for the parent organisation
data.parentOrganisation.capabilities string[] Capabilities available to the parent organisation
data.parentOrganisation.status string Status of the parent organisation: "active" or "suspended"
data.capabilities string[] Updated array of scopes/capabilities granted to this service actor
data.status string Updated status of the service actor: "active" or "suspended"
data.creatorUserId string ID of the user who created this service actor
data.createdAt string ISO 8601 timestamp when the service actor was originally created
data.updatedAt string ISO 8601 timestamp when the service actor was last updated

Delete Service Actor

Service actors are soft-deleted:

curl -X DELETE https://api.fermi.dev/public/v1/identity/service-actors/{service-actor-id} \
  -H "Authorization: Bearer fmk_live_your_api_key_here"

Response: 204 No Content

Service Actor Capabilities

Capabilities are scopes/permissions that define what a service actor can do. These are used for data access and service operations, not for provisioning.

Common capabilities:

  • analytics:query - Query analytics data
  • analytics:read - Read analytics data
  • analytics:write - Write analytics data
  • brain:read - Read brain data
  • brain:write - Write brain data
  • connectors:read - Read connector data
  • connectors:write - Write connector data
  • connectors:sync - Sync connector data

Note: Service actor capabilities determine what data and services the actor can access. These are different from API key scopes, which are used for provisioning operations.

Scopes and Permissions

Using Service Actors with Token Exchange

Service actors are used with token exchange to get short-lived JWT tokens:

  1. Create a service actor with appropriate capabilities
  2. Use your API key (with provision:token:exchange scope) to exchange for a service actor token
  3. Use the token for authenticated requests

Token Exchange

Service Actor Status

Service actors can have two statuses:

  • active: Service actor is active and can be used
  • suspended: Service actor is suspended and cannot be used

Suspended service actors cannot exchange tokens or make API calls.

Error Handling

Missing Scope

{
  "status": 403,
  "errors": {
    "auth": "Missing required scope: provision:service:create"
  }
}

Solution: Create an API key with provision:service:create scope.

Invalid Organization

{
  "status": 403,
  "errors": {
    "auth": "Service actor's parent organisation must match API key's organization"
  }
}

Solution: Ensure the organisationId matches your API key's organization.

Service Actor Not Found

{
  "status": 404,
  "message": "Service actor not found"
}

Solution: Verify the service actor ID is correct and belongs to your organization.

Examples

Python Example

import os
import requests

api_key = os.getenv("FERMI_API_KEY")
org_id = os.getenv("FERMI_ORG_ID")

response = requests.post(
    "https://api.fermi.dev/public/v1/identity/service-actors",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    },
    json={
        "name": "Python Integration",
        "organisationId": org_id,
        "capabilities": ["analytics:query", "analytics:read"]
    }
)

if response.status_code == 201:
    result = response.json()
    service_actor = result["data"]
    print(f"Created service actor: {service_actor['id']}")
    print(f"Organisation ID: {service_actor['organisation']['id']}")
    print(f"Parent Organisation ID: {service_actor['parentOrganisation']['id']}")
else:
    print(f"Error: {response.status_code} - {response.text}")

JavaScript/TypeScript Example

const apiKey = process.env.FERMI_API_KEY;
const orgId = process.env.FERMI_ORG_ID;

const response = await fetch('https://api.fermi.dev/public/v1/identity/service-actors', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'JavaScript Integration',
    organisationId: orgId,
    capabilities: ['analytics:query', 'analytics:read']
  })
});

if (response.ok) {
  const result = await response.json();
  const serviceActor = result.data;
  console.log(`Created service actor: ${serviceActor.id}`);
  console.log(`Organisation ID: ${serviceActor.organisation.id}`);
  console.log(`Parent Organisation ID: ${serviceActor.parentOrganisation.id}`);
} else {
  console.error(`Error: ${response.status} - ${await response.text()}`);
}

Next Steps