The official PHP SDK for the Administrate.dev REST API

v0.1.0 2026-02-19 05:14 UTC

This package is not auto-updated.

Last update: 2026-02-20 04:00:13 UTC


README

The official PHP SDK for the Administrate.dev REST API.

Administrate.dev is AI Agency Management software. It is a monitoring and management platform for AI agencies running n8n and AI automation workflows across multiple clients. It provides a single dashboard to track every workflow, every client, every failure, and all LLM costs, so you can catch problems before clients do and prove the value of your automations.

Key platform features:

  • Multi-instance monitoring -- See all n8n instances across every client in one place
  • Error tracking -- Real-time failure detection with automatic error categorization
  • LLM cost tracking -- Connect OpenAI, Anthropic, Azure, and OpenRouter accounts to attribute costs to specific clients
  • Workflow insights -- Execution counts, success rates, and time-saved ROI reporting
  • Sync health -- Know instantly when a data sync fails
  • Webhooks & API -- Full programmatic access for custom integrations

Installation

Install via Composer:

composer require administrate/sdk

Requires PHP 8.1+.

Quick start

use Administrate\Administrate;

$client = new Administrate(apiKey: 'sk_live_...');

// Get account info
$account = $client->account->get();
echo "{$account->name} ({$account->plan})";

// List all clients with auto-pagination
foreach ($client->clients->list() as $c) {
    echo "{$c->name} ({$c->code})\n";
}

// Check for failed executions across all instances
foreach ($client->executions->list(errorsOnly: true) as $execution) {
    echo "{$execution->workflow_name}: {$execution->error_category}\n";
}

// Get LLM cost summary
$costs = $client->llmCosts->summary();
echo "Total: $" . number_format($costs->data->summary->total_cost_cents / 100, 2);

Configuration

use Administrate\Administrate;

$client = new Administrate(
    apiKey: 'sk_live_...',            // Required. Must start with "sk_live_"
    baseUrl: 'https://...',           // Default: "https://administrate.dev"
    timeout: 30,                      // Request timeout in seconds. Default: 30
    maxRetries: 3,                    // Retry attempts for failed requests. Default: 3
);

You can also pass any PSR-18 compatible HTTP client:

$client = new Administrate(
    apiKey: 'sk_live_...',
    client: $yourPsr18Client,
);

API reference

All API keys are created in Settings > Developers within Administrate.dev. Tokens have three permission levels: read, write, and full.

Account

// Get current token info and account summary
$me = $client->account->me();
echo "{$me->token->name} ({$me->token->permission})";
echo "{$me->account->name} ({$me->account->plan})";

// Get full account details
$account = $client->account->get();

// Update account settings
$account = $client->account->update(
    name: 'My Agency',
    billingEmail: 'billing@example.com',
    timezone: 'Australia/Brisbane',
);

Clients

Clients represent the companies you manage automations for.

// List all clients (auto-paginates)
foreach ($client->clients->list() as $c) {
    echo "{$c->name} ({$c->code})\n";
}

// Get a client (includes 7-day metrics)
$c = $client->clients->get('com_abc123');
echo "{$c->metrics->success_rate}% success, {$c->metrics->time_saved_minutes} min saved";

// Create a client
$c = $client->clients->create(
    name: 'Acme Corp',
    code: 'acme',
    contactEmail: 'ops@acme.com',
    timezone: 'America/New_York',
);

// Update a client
$c = $client->clients->update('com_abc123', notes: 'Enterprise tier');

// Delete a client (requires full permission)
$client->clients->delete('com_abc123');

Instances

Instances are n8n deployments connected to Administrate.

// List all instances
foreach ($client->instances->list() as $inst) {
    echo "{$inst->name} ({$inst->sync_status})\n";
}

// Filter by client or sync status
foreach ($client->instances->list(clientId: 'com_abc123', syncStatus: 'error') as $inst) {
    echo "{$inst->name}: {$inst->last_sync_error}\n";
}

// Get an instance (includes 7-day metrics)
$inst = $client->instances->get('n8n_abc123');
echo "{$inst->metrics->executions_count} executions, {$inst->metrics->success_rate}% success";

// Connect a new n8n instance
$inst = $client->instances->create(
    clientId: 'com_abc123',
    name: 'Production n8n',
    baseUrl: 'https://n8n.acme.com',
    apiKey: 'n8n_api_key_here',
);

// Trigger a sync
$client->instances->sync('n8n_abc123', syncType: 'all');

// Sync all instances at once
$client->instances->syncAll(syncType: 'workflows');

// Update an instance
$inst = $client->instances->update('n8n_abc123', name: 'Staging n8n');

// Delete an instance
$client->instances->delete('n8n_abc123');

Workflows

// List workflows with filters
foreach ($client->workflows->list(clientId: 'com_abc123', active: true) as $wf) {
    echo "{$wf->name} (active: {$wf->is_active})\n";
}

// Search by name
foreach ($client->workflows->list(search: 'onboarding') as $wf) {
    echo $wf->name . "\n";
}

// Get a workflow (includes 7-day metrics)
$wf = $client->workflows->get('wfl_abc123');
echo "{$wf->metrics->success_rate}% success, {$wf->metrics->time_saved_minutes} min saved";

// Set time-saved estimates (for ROI reporting)
$wf = $client->workflows->update(
    'wfl_abc123',
    minutesSavedPerSuccess: 15,
    minutesSavedPerFailure: 5,
);

Executions

Executions are read-only records of workflow runs synced from n8n.

// List executions with filters
foreach ($client->executions->list(
    clientId: 'com_abc123',
    status: 'failed',
    startDate: '2025-01-01',
    endDate: '2025-01-31',
) as $ex) {
    echo "{$ex->workflow_name} - {$ex->status} ({$ex->duration_ms}ms)\n";
}

// Get only errors
foreach ($client->executions->list(errorsOnly: true) as $ex) {
    echo "{$ex->error_category}: {$ex->workflow_name}\n";
}

// Get execution details (includes error message and payload)
$ex = $client->executions->get('exe_abc123');
echo $ex->error_message;

Sync runs

// List sync run history
foreach ($client->syncRuns->list(instanceId: 'n8n_abc123', status: 'failed') as $run) {
    echo "{$run->sync_type} - {$run->status} ({$run->duration_seconds}s)\n";
}

// Get a specific sync run
$run = $client->syncRuns->get('syn_abc123');

// Get sync health across all instances
foreach ($client->syncRuns->health() as $entry) {
    echo "{$entry->instance_name} ({$entry->sync_status})\n";
    echo "  Workflows last synced: {$entry->workflows->last_synced_at}\n";
    echo "  Executions last synced: {$entry->executions->last_synced_at}\n";
}

Users

// List team members
foreach ($client->users->list() as $user) {
    echo "{$user->name} <{$user->email}> ({$user->role})\n";
}

// Get a user
$user = $client->users->get('usr_abc123');

// Invite a new team member
$invitation = $client->users->invite(email: 'new@example.com', role: 'member');
echo $invitation->expires_at;

// Change a user's role
$user = $client->users->update('usr_abc123', role: 'admin');

// Remove a user
$client->users->delete('usr_abc123');

Webhooks

// List webhooks
foreach ($client->webhooks->list() as $wh) {
    echo "{$wh->url} - " . implode(', ', $wh->events) . " (enabled: {$wh->enabled})\n";
}

// Create a webhook
$wh = $client->webhooks->create(
    url: 'https://example.com/hook',
    events: ['execution.failed', 'sync.failed'],
    description: 'Slack failure alerts',
);
echo $wh->secret; // Save this -- used to verify webhook signatures

// Update a webhook
$wh = $client->webhooks->update('whk_abc123', enabled: false);

// Regenerate the signing secret (old secret becomes invalid immediately)
$wh = $client->webhooks->regenerateSecret('whk_abc123');
echo $wh->secret;

// Delete a webhook
$client->webhooks->delete('whk_abc123');

API tokens

// List all tokens
foreach ($client->apiTokens->list() as $token) {
    echo "{$token->name} ({$token->permission}) - {$token->token_hint}\n";
}

// Create a token (the plain token is only returned once)
$token = $client->apiTokens->create(
    name: 'CI/CD Pipeline',
    permission: 'read',
    ipAllowlist: ['10.0.0.0/8'],
    expiresIn: '90_days',
);
echo $token->token; // sk_live_... -- save this immediately

// Update a token
$token = $client->apiTokens->update('tok_abc123', name: 'Updated Name');

// Revoke a token
$client->apiTokens->delete('tok_abc123');

LLM providers

Connect your AI provider accounts to track costs.

// List providers
foreach ($client->llmProviders->list() as $provider) {
    echo "{$provider->name} ({$provider->provider_type}) - {$provider->sync_status}\n";
}

// Get a provider (includes 7-day metrics)
$provider = $client->llmProviders->get('llm_abc123');
echo "{$provider->metrics->total_cost_cents}c, {$provider->metrics->total_tokens} tokens";

// Connect a new provider
$provider = $client->llmProviders->create(
    name: 'OpenAI Production',
    providerType: 'openai',  // openai, anthropic, openrouter, or azure
    apiKey: 'sk-...',
    organizationId: 'org-...',
);

// Trigger a cost sync
$client->llmProviders->sync('llm_abc123');

// Update a provider
$provider = $client->llmProviders->update('llm_abc123', name: 'OpenAI Staging');

// Delete a provider
$client->llmProviders->delete('llm_abc123');

LLM projects

Projects are discovered automatically when syncing a provider. Assign them to clients to attribute costs.

// List projects for a provider
foreach ($client->llmProjects->list('llm_abc123') as $project) {
    echo "{$project->name}: {$project->total_cost_cents}c ({$project->client_name})\n";
}

// Assign a project to a client
$project = $client->llmProjects->update(
    'llm_abc123', 'proj_456', clientId: 'com_abc123',
);

LLM costs

// Get cost summary (defaults to last 7 days)
$costs = $client->llmCosts->summary();
echo "Total: $" . number_format($costs->data->summary->total_cost_cents / 100, 2) . "\n";
echo "Tokens: {$costs->data->summary->total_tokens}\n";

// Breakdown by provider
foreach ($costs->data->providers as $p) {
    echo "  {$p->name}: $" . number_format($p->cost_cents / 100, 2) . "\n";
}

// Breakdown by model
foreach ($costs->data->models as $m) {
    echo "  {$m->model}: $" . number_format($m->cost_cents / 100, 2) . "\n";
}

// Daily trend
foreach ($costs->data->daily as $day) {
    echo "  {$day->date}: $" . number_format($day->cost_cents / 100, 2) . "\n";
}

// Custom date range
$costs = $client->llmCosts->summary(
    startDate: '2025-01-01',
    endDate: '2025-01-31',
);

// Costs by client
foreach ($client->llmCosts->byClient()->data as $entry) {
    echo "{$entry->name}: $" . number_format($entry->cost_cents / 100, 2) . "\n";
}

// Costs by provider
foreach ($client->llmCosts->byProvider()->data as $entry) {
    echo "{$entry->name}: $" . number_format($entry->cost_cents / 100, 2) . "\n";
}

Pagination

All ->list() methods return an IteratorAggregate that handles pagination automatically. By default, the API returns 25 items per page (max 100).

// Auto-paginate through all results
foreach ($client->clients->list() as $c) {
    echo $c->name . "\n";
}

// Control page size
foreach ($client->clients->list(perPage: 100) as $c) {
    echo $c->name . "\n";
}

// Get a single page
$page = $client->clients->list(perPage: 10)->firstPage();
echo "{$page->meta->total} total, {$page->meta->total_pages} pages\n";
foreach ($page as $c) {
    echo $c->name . "\n";
}

Error handling

The SDK raises typed exceptions for all API errors:

use Administrate\Administrate;
use Administrate\Exceptions\ApiException;
use Administrate\Exceptions\AuthenticationException;
use Administrate\Exceptions\NotFoundException;
use Administrate\Exceptions\RateLimitException;
use Administrate\Exceptions\ValidationException;

$client = new Administrate(apiKey: 'sk_live_...');

try {
    $c = $client->clients->get('com_nonexistent');
} catch (NotFoundException $e) {
    echo "Not found: {$e->getMessage()}";
} catch (AuthenticationException) {
    echo 'Invalid API key';
} catch (RateLimitException $e) {
    echo "Rate limited. Retry after {$e->retryAfter}s";
} catch (ValidationException $e) {
    echo "Invalid params: " . json_encode($e->body);
} catch (ApiException $e) {
    echo "API error {$e->statusCode}: {$e->getMessage()}";
}

Exception hierarchy:

Exception Status code Description
AdministrateException -- Base exception for all SDK errors
ApiException Any non-2xx Base for all HTTP API errors
AuthenticationException 401 Invalid or missing API key
PermissionDeniedException 403 Insufficient token permissions
NotFoundException 404 Resource does not exist
ValidationException 422 Invalid request parameters
RateLimitException 429 Rate limit exceeded (has retryAfter)
InternalServerException 5xx Server-side error
ConnectionException -- Failed to connect to the API
TimeoutException -- Request timed out

All ApiException subclasses expose statusCode and body (parsed JSON or string).

Retries

The SDK automatically retries failed requests with exponential backoff:

  • 429 (rate limited) -- Retries after the duration specified in the Retry-After header
  • 5xx (server errors) -- Retries with exponential backoff (0.5s, 1s, 2s, ...)
  • Connection errors and timeouts -- Retried with the same backoff schedule

By default, the SDK retries up to 3 times. Set maxRetries: 0 to disable:

$client = new Administrate(apiKey: 'sk_live_...', maxRetries: 0);

Requirements

License

MIT