OpsIQ Developer Documentation

Build on OpsIQ with the public action API, widget identity, webhooks, connector SDK, action gateway, and OpenAPI contract. These docs are customer-facing and apply to both hosted and self-hosted OpsIQ installs without exposing internal control-plane details.

Action API v1 stable OpenAPI 3.0 Bearer scopes Connector gateway

Start Here

OpsIQ exposes a stable namespaced action API at /api/v1.php. Send {"action":"meta.actions"} to discover the live catalog, then call actions such as crm.contacts.list, tickets.open, writing.reply, crm.deals.list, or kb.faq.save.

Machine-readable spec

The OpenAPI contract is always available at /api/v1/openapi.php. Import it into Postman, Insomnia, Stoplight, or your code generator.

curl /api/v1/openapi.php

Base URL

Use your own OpsIQ domain as the host. The path stays the same across installs.

https://your-opsiq-domain.com/api/v1.php
Every write operation should be tied to an API key scope and should pass through OpsIQ services or the connector gateway. Do not write directly to platform tables from custom code.

Authentication

Create an API key in OpsIQ, assign only the scopes that integration needs, and send it as a bearer token.

Authorization: Bearer opq_your_key_here
curl -X POST https://your-opsiq-domain.com/api/v1.php \
  -H "Authorization: Bearer opq_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"action":"meta.actions"}'

Keys can be rotated at any time. Store them server-side only. Browser widgets should use the widget identity token flow, not public API keys.

Every API v1 response includes a request_id. Keep it with integration logs so OpsIQ support can trace the exact authenticated request, workspace, action, outcome, and latency without storing the caller's raw IP address.

POST /api/v1.php
{"action":"meta.me"}

meta.me returns the verified key name, scopes, permissions mode, workspace, effective allowed/blocked actions, and recent usage summary for agency and enterprise integrations.

Scopes

ScopeAllowsTypical user
readRead-only access to non-CRM actions (e.g. meta and summary endpoints).Dashboards, reporting tools.
writingPerform write actions on non-CRM resources.Automation, integration jobs.
crm.readList and fetch CRM contacts.CRM sync, reporting tools.
crm.writeCreate and update CRM contacts (including tags and notes).Forms, stores, enrichment jobs.
adminAdministrative actions across the workspace.Platform connectors, owner integrations.

Contacts

POST/api/v1.php

List contacts with action <code>crm.contacts.list</code>.

Scope: crm.read

curl -X POST https://your-opsiq-domain.com/api/v1.php \
  -H "Authorization: Bearer opq_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"action":"crm.contacts.list","q":"ada","limit":25}'
POST/api/v1.php

Create or update contacts with <code>crm.contacts.save</code> or <code>crm.contacts.upsert</code>.

Scope: crm.write

{
  "action": "crm.contacts.upsert",
  "email": "ada@example.com",
  "name": "Ada Lovelace",
  "tags": ["trial", "developer"]
}
POST/api/v1.php

Fetch one contact with <code>crm.contacts.detail</code>, export with <code>crm.contacts.export</code>, or ask for next action with <code>crm.contacts.next_action</code>.

Scope: crm.read

Tickets

POST/api/v1.php

Open support tickets with action <code>tickets.open</code> or <code>tickets.open_guest</code>.

Scope: admin

{
  "action": "tickets.open",
  "customer_email": "customer@example.com",
  "customer_name": "Example Customer",
  "subject": "Cannot activate account",
  "body": "Activation email never arrived.",
  "priority": "high"
}
POST/api/v1.php

Use ticket actions for tags, saved views, assignment rules, SLA policies, and bulk queue actions.

Scope: admin

{"action":"tickets.bulk","operation":"close","ids":[123,124]}
Ticket write actions are operator-side actions and require an API key with admin scope. For platform-native ticket sync, prefer the connector action gateway.

Chats

POST/api/v1.php

Manage operator chat resources such as saved replies with actions like <code>chat.saved_replies.list</code>, <code>chat.saved_replies.save</code>, and <code>chat.saved_replies.add</code>.

Scope: admin

For visitor live chat, use the widget runtime. The public action API is for server-side integrations and operator tooling.

Analytics

POST/api/v1.php

Read CRM and business activity through action catalog reads such as <code>crm.events.list</code>, <code>crm.conversions.list</code>, and <code>crm.deals.list</code>.

Scope: crm.read

curl -X POST https://your-opsiq-domain.com/api/v1.php \
  -H "Authorization: Bearer opq_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"action":"crm.events.list","limit":50}'

Responses are workspace-scoped. Shared site groups do not merge per-domain visitor data unless the called action explicitly supports that aggregation.

Proactive Events

POST/api/v1.php

Record lifecycle and conversion activity with action API calls such as <code>crm.activities.record</code>, <code>crm.conversions.record</code>, or lifecycle evaluation actions.

Scope: crm.write

{
  "action": "crm.activities.record",
  "email": "customer@example.com",
  "event": "checkout.abandoned",
  "value": 129.50,
  "currency": "USD"
}

Use meta.actions to discover the currently enabled proactive and lifecycle actions on the install.

Knowledge Base

POST/api/v1.php

Read and manage FAQ/knowledge entries with <code>kb.faq.list</code>, <code>kb.faq.save</code>, <code>kb.faq.delete</code>, <code>kb.faq.generate</code>, and <code>kb.faq.import</code>.

Scope: admin/read

{
  "action": "kb.faq.save",
  "question": "How do I reset my password?",
  "answer": "Open Account Settings, choose Security, then Reset Password.",
  "status": "published"
}

The customer AI can use published knowledge-base content when answering visitors, depending on your AI instruction settings.

Widget And Identity

Install the OpsIQ widget on each website you want to track. Visitor data is collected per domain and stamped to the active site.

<script>
  window.OpsIQSettings = {
    siteKey: 'site_public_key',
    identity: {
      email: 'customer@example.com',
      name: 'Example Customer',
      external_id: 'cust_123'
    }
  };
</script>
<script src="https://your-opsiq-domain.com/widget.php" async></script>

Use identity when the visitor is logged in. For anonymous visitors, omit identity and OpsIQ will stitch later activity when the visitor identifies themselves.

Webhooks

Webhooks let other tools subscribe to OpsIQ activity. Register endpoints with crm.webhooks.save (or in the admin), then sign requests with the shared secret. The event names below come from the CRM event stream; call crm.events.catalog for the authoritative live list of subscribable events on your install. The same rows are also queryable by polling crm.events.list.

EventWhen it firesUseful for
crm.contact.createdA contact is created.CRM mirror / enrichment.
crm.contact.updatedA contact's fields change.Profile sync.
crm.deal.stage_changedA deal moves to a different stage.Pipeline automation.
crm.deal.created / crm.deal.won / crm.deal.lostA deal is created, marked won, or marked lost.Revenue reporting.
crm.task.createdA task is created.Workflow automation.
crm.outreach.replyAn outreach reply is classified.Sales alerting.
crm.agent.proposal_createdAn AI agent queues an Approve-Queue proposal.Human-in-the-loop review.

Also emitted: crm.company.created, crm.company.merged, crm.company.updated, crm.deal.updated.

{
  "event":"crm.contact.created",
  "event_id":"evt_123",
  "_workspace_key":"site_abc123",
  "contact_id":42
}

Connector SDK

Connectors are the production path for platform-specific actions. A connector defines metadata, settings, capability flags, and action specs. OpsIQ calls those actions through the gateway so validation, audit hooks, and platform sync stay consistent.

Manifest basics

{
  "slug":"example_platform",
  "name":"Example Platform",
  "version":"1.0.0",
  "manifest_version":1,
  "compatibility":{"opsiq_min":"1.0.0","opsiq_max":"*"},
  "capabilities":["native_api","tickets","customers"],
  "settings":[{"key":"api_key","type":"password","label":"API key"}]
}

Action shape

{
  "id":"ticket.reply",
  "label":"Reply to ticket",
  "params":{"ticket_id":"string","message":"string"},
  "requires_confirmation":true
}

Email connectors should expose mailbox/piping settings, not store or currency settings. Commerce connectors should expose order/customer/product actions. Support connectors should expose ticket, comment, assignment, and status actions.

Errors And Status Codes

StatusMeaningFix
400Invalid request body or parameter.Check JSON and required fields.
401Missing or invalid bearer token.Generate or rotate the API key.
403The API key does not have the required scope.Add the exact scope or use a more limited key per integration.
404Route or resource not found.Check the endpoint and id.
422Validation failed.Fix the field named in the error.
503A required service is unavailable.Check installation health and diagnostics.
{"success":false,"error":"Action 'tickets.open' is restricted on this API key.","permissions_mode":"restricted","request_id":"req_..."}

Authentication failures (missing, invalid, expired, or rate-limited key) return 401 with {"success":false,"error":"Invalid, expired, or rate-limited API key."}. A valid key that lacks a required scope, or is blocked by its permissions mode, returns 403.

Examples

JavaScript fetch

const res = await fetch('https://your-opsiq-domain.com/api/v1.php', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer opq_your_key_here',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    action: 'tickets.open',
    customer_email: 'customer@example.com',
    subject: 'Need help',
    body: 'The checkout page is failing.'
  })
});
const ticket = await res.json();

PHP cURL

$ch = curl_init('https://your-opsiq-domain.com/api/v1.php');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer opq_your_key_here',
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS => json_encode(['action' => 'crm.contacts.upsert', 'email' => 'ada@example.com', 'name' => 'Ada Lovelace']),
]);
$response = json_decode(curl_exec($ch), true);

Python requests

import requests

r = requests.post(
    'https://your-opsiq-domain.com/api/v1.php',
    headers={'Authorization': 'Bearer opq_your_key_here'},
    json={'action': 'crm.events.list', 'limit': 50},
    timeout=20,
)
r.raise_for_status()
print(r.json())