PORTAL API
Build integrations, automate workflows, and connect your repair shop with the tools you already use. Full REST API with webhooks, scoped authentication, and a plugin marketplace.
Overview
The PORTAL API is a RESTful JSON API for reading and writing repair tickets, customers, inventory, devices, and more. Every request requires a Bearer token. All dates are ISO 8601. Monetary values are decimals (not cents).
Quick Start
- Get an API key from Settings → API Integrations in your PORTAL dashboard
- Include it as
Authorization: Bearer {key}in every request - Make requests to
https://{shop}.portalhq.app/api/v1/{resource} - All responses are JSON with
"success": true/false
Authentication
Include your API key in the Authorization header on every request:
Key Types
| Prefix | Type | Purpose |
|---|---|---|
pk_live_ | Plugin Key | Production access for installed plugins |
dk_test_ | Developer Key | Sandbox testing during development |
ik_live_ | Internal Key | PORTAL internal services |
Errors & Responses
Successful responses return "success": true with a data field. Errors include a machine-readable code:
| Code | HTTP | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid API key |
FORBIDDEN | 403 | Key doesn't have required scope |
NOT_FOUND | 404 | Resource doesn't exist |
VALIDATION_ERROR | 422 | Invalid request body |
RATE_LIMITED | 429 | Slow down — see headers |
INTERNAL_ERROR | 500 | Server error (not your fault) |
Rate Limiting
Every response includes rate limit headers:
Pagination & Filtering
All list endpoints support pagination (default 50, max 200) and cursor-based navigation:
Tickets
Create, read, update tickets and manage notes, line items, and payments.
Customers
Manage customer records, search, and view ticket history.
Catalog & Inventory
Manage your parts catalog and stock levels.
Devices
View device inventory (phones, tablets, etc. in the buy/sell pipeline).
Purchase Orders
Create and manage purchase orders for supplier ordering.
Store & Users
Shop info, ticket statuses, feature flags, and active users.
Webhooks Management
Register, update, and delete webhook endpoints programmatically.
Webhook Events
When events occur in PORTAL, we send an HTTP POST to your registered webhook URL with a signed JSON payload.
Payload Structure
Webhook Security
Every delivery includes HMAC-SHA256 signature headers for verification:
Verification — PHP
Verification — Node.js
Scopes Reference
Each API key is granted specific scopes controlling what data it can access. Plugins declare required scopes in their manifest; shop owners approve them on install.
Plugin Manifest
Every plugin is defined by a portal-plugin.json manifest file submitted for review:
Plugin Categories
UI Widgets
Plugins can embed small UI panels inside PORTAL pages via sandboxed iframes, communicating with the host page through postMessage.
Widget Locations
| Location ID | Where | Max Height |
|---|---|---|
ticket_sidebar | Ticket detail right sidebar | 300px |
ticket_toolbar | Ticket toolbar action buttons | 40px |
customer_sidebar | Customer profile sidebar | 300px |
dashboard_card | Main dashboard area | 400px |
settings_panel | Plugin settings page | Unlimited |
queue_banner | Top of ticket queue | 80px |
Communication
?token=wt_... parameter when loading your widget iframe. Exchange it via POST /api/v1/widgets/verify-token to get context data.