Developer platform · REST · webhooks · SDKs

Make your platform AI-operable.

OpsIQ exposes a clean REST API, HMAC-signed webhooks, an action-contract registry and ready-to-ship SDKs. Define what events fire from your system, what actions the AI is allowed to run, and what data is safe to read. OpsIQ handles signatures, retries, audit logs and confirmation flows for you.

HMAC-SHA256 both waysPHP · Node · Python SDKsOpenAPI 3.0.3 contract100% audit coverage
Signed request in
Signed webhook out → 200 OK
Live curl → OpsIQ → signed webhook POST /v1/actions/run X-OpsIQ-Signature { "action": "refund_invoice", "confirmed": true } VERIFY · RUN · AUDIT signature ✓ role + scope ✓ audit row written @opsiq/sdk widget on("action.executed") verify HMAC → handle 200 OK
3official SDKs: PHP, Node, Python
HMACSHA-256 signed on every request
40+universal events to subscribe
100%audit-log coverage on actions
The request lifecycle

Request in. Signed webhook out.

You POST to the OpsIQ API with your scoped Bearer key. OpsIQ checks scope and role, runs the contracted action, writes an audit row - then fires an HMAC-signed webhook back to your endpoint. Every hop is authenticated, idempotent and retried on failure.

HMAC-SHA256 webhooks - inbound and outbound webhook payloads are signed over the raw body; API calls authenticate with a scoped Bearer key.
Automatic retries - failed deliveries back off and retry, with a delivery ID you can trace.
Idempotency keys - replay-safe by design, so a retried delivery never double-acts.
Your app POST /v1/actions/run X-OpsIQ-Signature X-OpsIQ-Timestamp VERIFY - RUN - AUDIT Your endpoint POST /webhooks verify HMAC 200 OK signature verified scope + role checked contracted action run audit row written SIGNED WEBHOOK PAYLOAD { "event": "action.executed", "delivery_id": "dlv_8f2a9", "idempotency_key": "idem_31c7", "signature": "sha256=9c4e0a7b..." } delivered
01 signed request 02 verify HMAC 03 run contract 04 write audit row 05 signed webhook
Quickstart

From zero to a live integration in four steps.

Generate a key, fire your first event, subscribe a webhook, register an action. You can run the whole loop against the sandbox before touching production data.

Sandbox consoleConnected
DEVELOPER CONSOLE · sandbox 1 · Generate key opq_live_xxx · one scoped Bearer key 2 · Fire an event POST /v1/events/fire "order.shipped" 3 · Subscribe a webhook → https://api.you.com/webhooks 4 · Register an action saas.refund_invoice · audited
PromoteSandbox → production, same code
01

Get a key

Sign up and generate a scoped Bearer API key (opq_…) in developer settings, and give each integration only the surfaces it needs.

02

Fire & subscribe

POST a signed events/fire (or use an SDK), then point any URL at any event, signed, with a delivery ID and back-off retries.

03

Register an action

Declare a signed action contract so the AI can safely run operations, with role checks, confirmation policy and a full audit trail.

How it fits together

One connector pattern. Five clean primitives.

Anything platform-specific lives in a connector. The OpsIQ core stays generic, the AI stays predictable, and your integration stays auditable.

01
Triggers

Tell OpsIQ what just happened.

Fire universal events from your platform - or your own custom event names. Every subscriber reacts in real time, in priority order.

Event reference
invoice.paid events.fire() AI brainlive context rulespriority 20 mirrorwrite first webhooksigned
Universal + custom eventsinvoice.paid, ticket.created, subscription.cancelled, customer.signed_up or your own. Fan-out subscribersThe AI brain, automation rules, mirror connectors and your webhook endpoints all react. Priority orderDeterministic dispatch so mirrors write before alerts fire.
02 / Action contracts

Tell OpsIQ what the AI is allowed to do.

An action contract is a signed JSON declaration: what the action does, which roles can run it, what parameters it accepts, whether confirmation is required, and the endpoint to call.

Action schema
The AI can't invent actionsIt can only ask to run ones you've registered. Confirmation policyRisky actions trigger a preview card before any side-effect. Role + surface gatingEvery action declares the roles and surfaces allowed to run it.
action contract - JSON
{
  "key": "saas.refund_invoice",
  "label": "Refund a paid invoice",
  "surface": ["admin"],
  "roles": ["owner", "billing_admin"],
  "requires_confirmation": true,
  "params": {
    "invoice_id": { "type": "int", "required": true },
    "reason": { "type": "string", "max": 500 }
  },
  "endpoint": "https://api.you.com/refund",
  "audit": true
}
03 / Signed webhooks

Push events to your stack - with cryptographic proof.

Subscribe any URL to any event. OpsIQ POSTs the JSON payload signed with HMAC-SHA256 over the raw body - verify it in a few lines.

Replay protectionTraceable delivery IDBack-off retries
Webhook reference
verify webhook - php
$raw = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_OPSIQ_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', $raw, $secret); // hex digest, no prefix
if (!hash_equals($expected, $sig)) http_response_code(401);
$event = json_decode($raw, true);
04 / SDKs

Drop-in clients for the language you already use.

Three official SDKs handle authentication, signing, retries, idempotency keys and typed responses. Or stay framework-free - every SDK is a thin wrapper around the same REST surface.

client examples
import { OpsIQ } from "@opsiq/sdk";
const ops = new OpsIQ({ apiKey: process.env.OPSIQ_KEY });

await ops.events.fire("order.shipped", {
  customer_id: 421,
  order_ref: "NB-9182",
  carrier: "DHL"
});

const result = await ops.actions.run("saas.send_kb_link", {
  ticket_id: 5519,
  article: "how-to-reset-password"
});
use OpsIQ\Client;

$ops = new Client([
  'api_key' => getenv('OPSIQ_KEY'),
]);

$ops->events->fire('order.shipped', [
  'customer_id' => 421,
  'order_ref' => 'NB-9182',
]);

$result = $ops->actions->run('saas.send_kb_link', [
  'ticket_id' => 5519,
  'article' => 'how-to-reset-password',
]);
from opsiq import OpsIQ

ops = OpsIQ(
    api_key=os.environ["OPSIQ_KEY"],
)

ops.events.fire("order.shipped", {
    "customer_id": 421,
    "order_ref": "NB-9182",
})

result = ops.actions.run("saas.send_kb_link", {
    "ticket_id": 5519,
    "article": "how-to-reset-password",
})
PHP 8.4+Node.js 18+Python 3.10+REST · OpenAPI 3.0.3
05 / The connector pattern

Build once. Plug into anything.

A connector is a folder with one PHP class. OpsIQ discovers it, the registry wires the events, and your platform-specific code stays cleanly separated from the core.

Connector guide
Five hooksidentityProviders(), contextProviders(), registerActions(), subscribers(), handleWebhook(). Manifest-drivenactions.json and settings.json declare contracts and config. Auto-discoveredDrop the folder in, sign it, enable it in admin.
From intent to safe action

Plain English in. Audited operation out.

OpsIQ never invents the right call. It walks through the registered contracts, prepares the payload, asks for confirmation when the action requires it, and produces a complete audit row when it executes, so an AI that can act never becomes an AI you can't trust.

Contract-bound. The AI only proposes actions you've registered.
Confirm before side-effects. Risky actions surface a preview card first.
Total recall. Every prompt, response and action result captured in AI History.
4 stepsintent → audit
HMACsigned before execute
"refund Adam's last invoice" Step 1 · intent resolution → matched: saas.refund_invoice surface: admin · role: owner · Step 2 validate Step 3 · Confirm & sign preview card · invoice #8421 Confirm Step 4 · Audit row actor · prompt · result · 412ms Owner-only · exportable as CSV
No invented callscontract registry only
Confirm-gatedpreview before side-effects
100% auditedprompt + response + result
Reference

API surface at a glance.

Every core endpoint, its auth, idempotency and per-key rate limit. The full machine-readable contract lives in the OpenAPI 3.0.3 reference.

OpenAPI 3.0.3 reference
EndpointAuthIdempotentRate limit
WriteSigned side-effect surfaces
POST /v1/events/fireHMACYes1000 / min
POST /v1/actions/runHMACYes200 / min
POST /v1/webhooks/testHMACYes60 / min
ReadContext, tickets and connector inventory
GET /v1/customers/{id}HMACYes2000 / min
GET /v1/ticketsHMACYes2000 / min
GET /v1/connectorsHMACYes2000 / min

Rate limits are per key and returned on every response as X-OpsIQ-RateLimit-Remaining; exceeding a limit returns 429 with a Retry-After header. The full machine-readable contract (every endpoint, schema and error) lives in the OpenAPI 3.0.3 reference.

Build a connector

Ship a connector in five steps.

A connector is a self-contained folder. OpsIQ discovers it, the registry wires the events, and your platform-specific code never leaks into the core.

1Scaffold a folder with connector.php extending AbstractConnector.
2Declare actions.json and settings.json manifests.
3Implement identity, context and webhook providers.
4Subscribe to the events you care about.
5Sign it, drop it in, enable it in admin.
Test before you ship

A sandbox key and a webhook tester.

Every workspace exposes a sandbox: a separate scoped key that hits the same API surface without touching production data. Use POST /v1/webhooks/test to fire a signed sample delivery at your endpoint and confirm your signature verification before going live. Self-hosted installs run the identical code path, with no behavioural drift between cloud and on-prem.

Sandbox keys Webhook tester Cron-driven jobs Cloud & self-hosted parity
connector.php · php
class AcmeConnector extends AbstractConnector { public function key(): string { return 'acme'; } // Resolve who the actor is public function identityProviders(): array { return [new AcmeIdentityProvider()]; } // Feed live data into the AI prompt public function contextProviders(): array { return [new AcmeContextProvider()]; } // React to OpsIQ events public function subscribers(): array { return ['invoice.paid' => [new BillingMirror()]]; } // Receive inbound webhooks from Acme public function handleWebhook(array $body): void { /* … */ } }
⚖️ How it compares

OpsIQ vs a DIY integration.

What a contract-bound, signed, audited platform gives you that rolling your own webhooks and AI-action plumbing never will.

CapabilityRoll your ownOpsIQ
HMAC-signed requests & webhooks (both ways) Hand-rolled
Idempotency keys + replay protection DIY
Automatic back-off retries with delivery IDs DIY queue
Action-contract registry (AI can't invent calls)
Confirmation policy before side-effects
100% audit-log coverage on actions Manual logging
Official PHP / Node / Python SDKs Write your own
OpenAPI 3.0.3 machine-readable contract Maybe
Sandbox keys + webhook tester Build a staging rig
Cloud & self-hosted parity (same code path) Varies
Connector pattern: platform code stays isolated
FAQ

Developer questions, answered.

Auth, signatures, SDKs, sandboxing and the connector model: everything you'll ask before the first request.

API calls authenticate with a single scoped Bearer key: send Authorization: Bearer opq_…. OpsIQ checks the key's scope and the actor's role before anything runs. Webhooks are separate: every webhook OpsIQ sends carries an X-OpsIQ-Signature (a hex HMAC-SHA256 of the raw body) and an X-OpsIQ-Timestamp for replay protection, so you can verify us in return, and inbound webhooks you send are verified the same way.
No. The AI can only propose actions that exist in your action-contract registry. It cannot invent a call. Each contract declares the surfaces, roles and parameters allowed, and any action marked requires_confirmation surfaces a preview card to a human before the side-effect runs.
Recompute hash_hmac('sha256', $rawBody, $secret) (a hex digest with no prefix) and compare it to the X-OpsIQ-Signature header with a constant-time check (hash_equals). Every delivery also carries a timestamp, an idempotency key and a delivery ID you can trace. The PHP snippet on this page is the whole verification.
Deliveries that don't return a 200 are retried with exponential back-off, each carrying the same idempotency key so a retried delivery never double-acts. You can trace every attempt by delivery ID in admin or your logs.
Official SDKs for PHP 8.4+, Node.js 18+ and Python 3.10+ handle signing, retries, idempotency keys and typed responses. They're thin wrappers around the REST surface, so you can also generate your own client from the published OpenAPI 3.0.3 contract or call the API directly.
Yes. Every workspace exposes a sandbox with its own scoped key that hits the same API surface without touching production data, plus POST /v1/webhooks/test to fire a signed sample delivery at your endpoint and confirm your verification before going live.
Yes. Self-hosted installs run the identical code path (the same signing, the same connector registry, the same OpenAPI contract) so there's no behavioural drift between cloud and on-prem.
A connector is a self-contained folder with one PHP class extending AbstractConnector, plus actions.json and settings.json manifests. You implement identityProviders(), contextProviders(), registerActions(), subscribers() and handleWebhook(). OpsIQ auto-discovers it, wires the events and keeps your platform-specific code cleanly separated from the core.