Skip to content

Workflow Metrics

Operational endpoints for monitoring workflow health across the tenant. Use these to build dashboards, set up alerting thresholds, or identify stuck workflows.

Required Role

MEMBER

Headers

HeaderValueRequired
AuthorizationBearer <token>Yes
X-Tenant-IDTenant identifier stringYes

Aggregate Metrics

Retrieve a count of workflows grouped by status. This gives a high-level snapshot of the system's current operational state.

Endpoint

GET /api/v1/workflows/metrics

Response Body

json
{
  "READY": 14,
  "RUNNING": 203,
  "COMPLETED": 98421,
  "FAILED": 37,
  "COMPENSATING": 2,
  "COMPENSATED": 18,
  "COMPENSATION_FAILED": 1
}

The response is a flat object mapping each status to its current workflow count. All status keys are always present, with a value of 0 when no workflows exist in that state.

Status Values

StatusTerminalDescription
READYNoCreated but not yet started.
RUNNINGNoActively executing.
COMPLETEDYesFinished successfully.
FAILEDYesTerminated due to an unrecoverable error.
COMPENSATINGNoExecuting compensation (rollback) steps.
COMPENSATEDYesCompensation completed successfully.
COMPENSATION_FAILEDYesCompensation steps also failed.

Examples

bash
curl -X GET "https://policy.aster-lang.dev/api/v1/workflows/metrics" \
  -H "Authorization: Bearer <token>" \
  -H "X-Tenant-ID: acme-corp"
js
const response = await fetch(
  'https://policy.aster-lang.dev/api/v1/workflows/metrics',
  {
    headers: {
      Authorization: 'Bearer <token>',
      'X-Tenant-ID': 'acme-corp',
    },
  }
);

const metrics = await response.json();

// Alert if any workflows are stuck in a compensation failure state
if (metrics.COMPENSATION_FAILED > 0) {
  console.warn(`${metrics.COMPENSATION_FAILED} workflow(s) require manual intervention`);
}

List Workflows by Status

Retrieve a list of workflow IDs currently in a given status. Useful for drilling into specific workflows after identifying a concern from the aggregate metrics.

Endpoint

GET /api/v1/workflows/by-status/{status}

Path Parameters

ParameterTypeDescription
statusstringThe workflow status to filter by. Must be one of the values listed in the Status Values table above.

Query Parameters

ParameterTypeRequiredDescription
limitintegerNoMaximum number of workflow IDs to return. Defaults to 100. The server may enforce its own maximum cap.

Response Body

json
{
  "status": "RUNNING",
  "workflowIds": [
    "wf-abc123",
    "wf-def456",
    "wf-ghi789"
  ],
  "count": 3
}
FieldTypeDescription
statusstringThe requested status (mirrors the path parameter).
workflowIdsstring[]List of matching workflow identifiers, ordered by creation time descending.
countintegerNumber of IDs returned in this response. May be less than the total if results were capped by limit.

Examples

bash
# List up to 100 running workflows (default limit)
curl -X GET "https://policy.aster-lang.dev/api/v1/workflows/by-status/RUNNING" \
  -H "Authorization: Bearer <token>" \
  -H "X-Tenant-ID: acme-corp"

# List up to 10 failed workflows
curl -X GET "https://policy.aster-lang.dev/api/v1/workflows/by-status/FAILED?limit=10" \
  -H "Authorization: Bearer <token>" \
  -H "X-Tenant-ID: acme-corp"
js
async function getWorkflowsByStatus(status, limit = 100) {
  const params = new URLSearchParams({ limit: String(limit) });
  const response = await fetch(
    `https://policy.aster-lang.dev/api/v1/workflows/by-status/${status}?${params}`,
    {
      headers: {
        Authorization: 'Bearer <token>',
        'X-Tenant-ID': 'acme-corp',
      },
    }
  );
  return response.json();
}

// Inspect the first 10 failed workflows
const { workflowIds } = await getWorkflowsByStatus('FAILED', 10);

for (const id of workflowIds) {
  const stateRes = await fetch(
    `https://policy.aster-lang.dev/api/v1/workflows/${id}/state`,
    { headers: { Authorization: 'Bearer <token>', 'X-Tenant-ID': 'acme-corp' } }
  );
  const state = await stateRes.json();
  console.log(id, state.updatedAt, state.lastEventSeq);
}

HTTP Status Codes

StatusMeaning
200 OKRequest succeeded.
400 Bad RequestInvalid status value or malformed limit parameter.
401 UnauthorizedMissing or invalid bearer token.
403 ForbiddenToken is valid but the caller lacks the MEMBER role.
500 Internal Server ErrorUnexpected engine failure.

Released under the MIT License.