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
| Scope | Allows | Typical user |
read | Read-only access to non-CRM actions (e.g. meta and summary endpoints). | Dashboards, reporting tools. |
writing | Perform write actions on non-CRM resources. | Automation, integration jobs. |
crm.read | List and fetch CRM contacts. | CRM sync, reporting tools. |
crm.write | Create and update CRM contacts (including tags and notes). | Forms, stores, enrichment jobs. |
admin | Administrative actions across the workspace. | Platform connectors, owner integrations. |
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.
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.
| Event | When it fires | Useful for |
crm.contact.created | A contact is created. | CRM mirror / enrichment. |
crm.contact.updated | A contact's fields change. | Profile sync. |
crm.deal.stage_changed | A deal moves to a different stage. | Pipeline automation. |
crm.deal.created / crm.deal.won / crm.deal.lost | A deal is created, marked won, or marked lost. | Revenue reporting. |
crm.task.created | A task is created. | Workflow automation. |
crm.outreach.reply | An outreach reply is classified. | Sales alerting. |
crm.agent.proposal_created | An 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
| Status | Meaning | Fix |
400 | Invalid request body or parameter. | Check JSON and required fields. |
401 | Missing or invalid bearer token. | Generate or rotate the API key. |
403 | The API key does not have the required scope. | Add the exact scope or use a more limited key per integration. |
404 | Route or resource not found. | Check the endpoint and id. |
422 | Validation failed. | Fix the field named in the error. |
503 | A 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())