API Reference
Harness API — v1 · Base:https://harness.jheel.io
The jheel.io Harness API provides asynchronous document extraction, enterprise RAG queries, autonomous agent management, and vendor integration configuration — all through a consistent, authenticated REST interface.
Workflow overview
For document extraction, the standard flow is:
- Create a session — a container for one or more related documents.
- Upload one or more documents to the session.
-
Poll the document endpoint until
ExtractedJSONis populated orErrorMessageis non-empty.
ExtractedJSON will be available
immediately after upload.
Response Envelope
Every API response is wrapped in a standard envelope. The actual
resource data lives inside the Data field.
{
"Success": true,
"Message": "session created",
"Data": { ... },
"RequestID": "req_3f8a1c2e..."
}
| Field | Type | Description |
|---|---|---|
Success |
boolean | true on success, false on error. |
Message |
string | Human-readable outcome description. |
Data |
object | null | The response payload. null for void operations. |
RequestID |
string | Unique identifier for this request. Also returned in the
X-Request-ID response header. Include in
support requests.
|
Error responses follow the same envelope with Success: false
and an Error field instead of Data:
{
"Success": false,
"Error": "validation failed",
"Fields": { "Prompt": "is required" },
"RequestID": "req_3f8a1c2e..."
}
All IDs returned by the API are prefixed strings, not integers — for example
"session-0196a8bc-..." or "agent-0196a9d1-...".
Authentication
Most endpoints require an API key passed in the
X-API-KEY request header. API keys are created
per-user via the Create API Key
endpoint after registering.
The /billing and /api-keys endpoints
instead require a JWT bearer token obtained from
the login endpoint.
API key header
X-API-KEY: your_api_key_here
JWT bearer header
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Requests without valid credentials return
401 Unauthorized. Requests on a tenant with a
depleted credit balance return 402 Payment Required.
Base URL
https://harness.jheel.io
All endpoints are relative to this base URL. HTTPS only.
API Keys — List
Returns all API keys for the authenticated user. Requires a JWT bearer token from the login endpoint.
Headers
Authorization: Bearer <jwt-token>
Example request
GET https://harness.jheel.io/api-keys Authorization: Bearer eyJhbGci...
Example response
{
"Success": true,
"Data": {
"Items": [
{
"ID": "apikey-0196a8bc-4f21-7a3e-b891-c2d3e4f5a6b7",
"TenantID": "tenant-0196a8ba-...",
"UserID": "user-0196a8bb-...",
"Name": "production",
"Prefix": "3f8a1c2e4d5b6a7f",
"LastUsedAt": "2026-06-14T11:30:00Z",
"CreatedAt": "2026-06-14T09:00:00Z",
"UpdatedAt": "2026-06-14T11:30:00Z",
"RevokedAt": null
}
]
}
}
API Keys — Create
Creates a new API key. The raw key value is returned once and only once — store it securely. Subsequent requests return only the prefix for identification.
Headers
Authorization: Bearer <jwt-token> Content-Type: application/json
Request body
| Field | Type | Required | Description |
|---|---|---|---|
Name |
string | required | A label for this key, e.g. "production" or
"ci-pipeline".
|
Example request
POST https://harness.jheel.io/api-keys
Authorization: Bearer eyJhbGci...
Content-Type: application/json
{
"Name": "production"
}
Example response
{
"Success": true,
"Message": "api key created",
"Data": {
"ID": "apikey-0196a8bc-4f21-7a3e-b891-c2d3e4f5a6b7",
"Name": "production",
"Prefix": "3f8a1c2e4d5b6a7f",
"Key": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
}
}
Key field is only present in the create response.
It is never returned again. Copy it now.
API Keys — Revoke
Permanently revokes an API key. Revoked keys are rejected immediately on the next request. This action cannot be undone.
Headers
Authorization: Bearer <jwt-token>
Path parameters
| Parameter | Description |
|---|---|
id |
The ID of the key to revoke, as returned by
the list or create endpoint.
|
Example request
DELETE https://harness.jheel.io/api-keys/apikey-0196a8bc-4f21-7a3e-b891-c2d3e4f5a6b7 Authorization: Bearer eyJhbGci...
Example response
{
"Success": true,
"Message": "api key revoked",
"Data": {
"ID": "apikey-0196a8bc-4f21-7a3e-b891-c2d3e4f5a6b7",
"Status": "revoked"
}
}
Create Session
Creates a new extraction session. A session is a container for
one or more related documents. Use a meaningful
ClientID to correlate sessions with your own
records — it is stored as-is and returned in all session
responses.
Headers
Accept: application/json Content-Type: application/json X-API-KEY: <api-key>
Request body
| Field | Type | Required | Description |
|---|---|---|---|
ClientID |
string | required | Your own reference identifier for this session. |
Example request
POST https://harness.jheel.io/harness/session
Content-Type: application/json
X-API-KEY: your_api_key_here
{
"ClientID": "q4-audit-2026"
}
Example response
{
"Success": true,
"Message": "session created",
"Data": {
"SessionID": "session-0196a8bc-4f21-7a3e-b891-c2d3e4f5a6b7",
"ClientID": "q4-audit-2026",
"Data": null,
"Created": "2026-06-14T09:00:00Z",
"Updated": "2026-06-14T09:00:00Z"
}
}
Python
import requests
BASE_URL = "https://harness.jheel.io"
API_KEY = "your_api_key_here"
response = requests.post(
f"{BASE_URL}/harness/session",
headers={
"Accept": "application/json",
"Content-Type": "application/json",
"X-API-KEY": API_KEY,
},
json={"ClientID": "q4-audit-2026"},
)
response.raise_for_status()
session = response.json()["Data"]
session_id = session["SessionID"] # → "session-0196a8bc-..."
Get Session
Retrieves a session by its ID.
Headers
Accept: application/json X-API-KEY: <api-key>
Example request
GET https://harness.jheel.io/harness/session/session-0196a8bc-4f21-7a3e-b891-c2d3e4f5a6b7 Accept: application/json X-API-KEY: your_api_key_here
Example response
{
"Success": true,
"Data": {
"SessionID": "session-0196a8bc-4f21-7a3e-b891-c2d3e4f5a6b7",
"ClientID": "q4-audit-2026",
"Data": null,
"Created": "2026-06-14T09:00:00Z",
"Updated": "2026-06-14T09:00:00Z"
}
}
Upload Document
Uploads a document to an existing session. Extraction begins immediately and runs asynchronously — poll Get Document to retrieve results. Storage counts against your tenant's storage cap (10 GB default).
Headers
Accept: application/json X-API-KEY: <api-key>
Content-Type manually for multipart
uploads. Let your HTTP client set it — it must include the
boundary parameter automatically.
Multipart form fields
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | required | Document type. Accepted values: invoice,
receipt, credit_note,
debit_note, purchase_order,
contract, other |
file |
file | required | The document file. Accepted formats: PDF, PNG, JPG, DOCX, XLSX. |
Example request
POST https://harness.jheel.io/harness/session/session-0196a8bc-.../document Accept: application/json X-API-KEY: your_api_key_here type=invoice file=@q4-invoice.pdf
Example response
{
"Success": true,
"Message": "document accepted",
"Data": {
"DocumentID": "document-0196a8bd-1a2b-7c3d-e4f5-a6b7c8d9e0f1",
"Document": "q4-invoice__document-0196a8bd-....pdf",
"DocumentName": "q4-invoice.pdf",
"MimeType": "application/pdf",
"Type": "invoice",
"ExtractedJSON": null,
"CostUSD": 0,
"StorageBytes": 204312,
"VectorBytes": 0,
"ErrorMessage": "",
"ResponseTimeMs": 0,
"Created": "2026-06-14T09:01:00Z",
"Updated": "2026-06-14T09:01:00Z"
}
}
Python
import requests
session_id = "session-0196a8bc-..."
response = requests.post(
f"{BASE_URL}/harness/session/{session_id}/document",
headers={
"Accept": "application/json",
"X-API-KEY": API_KEY,
},
data={"type": "invoice"},
files={"file": ("q4-invoice.pdf", open("q4-invoice.pdf", "rb"), "application/pdf")},
)
response.raise_for_status()
document = response.json()["Data"]
document_id = document["DocumentID"] # → "document-0196a8bd-..."
Get Document
Retrieves the current processing status and extracted data for a document. Poll this endpoint after upload until extraction completes or fails.
Headers
Accept: application/json X-API-KEY: <api-key>
Example request
GET https://harness.jheel.io/harness/session/session-0196a8bc-.../document/document-0196a8bd-... Accept: application/json X-API-KEY: your_api_key_here
Example response — extraction complete
{
"Success": true,
"Data": {
"DocumentID": "document-0196a8bd-1a2b-7c3d-e4f5-a6b7c8d9e0f1",
"Document": "q4-invoice__document-0196a8bd-....pdf",
"DocumentName": "q4-invoice.pdf",
"MimeType": "application/pdf",
"Type": "invoice",
"CostUSD": 0.002346,
"StorageBytes": 204312,
"VectorBytes": 0,
"ResponseTimeMs": 5302,
"ErrorMessage": "",
"ExtractedJSON": {
"VendorName": "Meridian Supply Co.",
"InvoiceDate": "2026-06-01",
"InvoiceNumber": "INV-4892",
"TotalAmount": 12450.00,
"LineItems": [
{
"Description": "Professional Services — Q2",
"Quantity": 1,
"UnitPrice": 12450.00,
"Total": 12450.00
}
],
"AdditionalFields": []
},
"Created": "2026-06-14T09:01:00Z",
"Updated": "2026-06-14T09:01:05Z"
}
}
Response fields
| Field | Type | Description |
|---|---|---|
ExtractedJSON |
object | null | Null while processing. Populated on completion. |
ErrorMessage |
string | Empty on success. Failure detail if extraction failed. |
CostUSD |
float | Processing cost for this document in USD. |
StorageBytes |
integer | Bytes consumed by the original file in storage. |
VectorBytes |
integer | Bytes consumed by embedding vectors for this document. |
ResponseTimeMs |
integer | Extraction processing time in milliseconds. |
Polling Guide
Extraction is asynchronous. After uploading, poll the Get Document endpoint at a regular interval until a terminal state is reached.
States
| State | ExtractedJSON | ErrorMessage |
|---|---|---|
| Processing | null |
"" (empty) |
| Complete | object | "" (empty) |
| Failed | null |
non-empty string |
Python polling example
import time
import requests
def poll_document(session_id: str, document_id: str) -> dict:
url = f"{BASE_URL}/harness/session/{session_id}/document/{document_id}"
headers = {"Accept": "application/json", "X-API-KEY": API_KEY}
while True:
resp = requests.get(url, headers=headers)
resp.raise_for_status()
data = resp.json()["Data"]
if data.get("ErrorMessage"):
raise RuntimeError(f"Extraction failed: {data['ErrorMessage']}")
if data.get("ExtractedJSON") is not None:
return data["ExtractedJSON"]
print("Processing… retrying in 2s")
time.sleep(2)
result = poll_document(
session_id = "session-0196a8bc-...",
document_id = "document-0196a8bd-...",
)
print(result["VendorName"]) # → "Meridian Supply Co."
RAG — Query Documents
Once documents have been processed in a session, they form a queryable knowledge base. Submit a natural-language question against the session's document corpus and receive a structured answer with source attribution and confidence scoring.
Headers
Accept: application/json Content-Type: application/json X-API-KEY: <api-key>
Request body
| Field | Type | Required | Description |
|---|---|---|---|
SessionID |
string | required | The session whose documents will be queried. |
Q |
string | required | Natural-language question. No special syntax required. |
Example request
POST https://harness.jheel.io/harness/rag/query
Content-Type: application/json
X-API-KEY: your_api_key_here
{
"SessionID": "session-0196a8bc-...",
"Q": "What are the payment terms across all Q4 vendor invoices?"
}
Example response
{
"Success": true,
"Data": {
"Answer": "Net-30 is specified in 11 of 14 vendor invoices reviewed. Three vendors — Meridian Supply Co. (INV-4892), Apex Materials (INV-4834), and Bright Tech (INV-4821) — specify Net-45 terms.",
"Sources": [
{
"DocumentID": "document-0196a8bd-...",
"Document": "meridian-inv.pdf",
"Page": 1
},
{
"DocumentID": "document-0196a8be-...",
"Document": "apex-inv.pdf",
"Page": 1
}
],
"Confidence": 0.94,
"SessionID": "session-0196a8bc-..."
}
}
Response fields
| Field | Type | Description |
|---|---|---|
Answer |
string | Natural-language answer synthesised from the document corpus. |
Sources |
array | Documents and pages that informed the answer. |
Confidence |
float (0–1) | Model confidence in the answer. Values below 0.7 indicate low certainty. |
Agents — Create
Creates and activates an autonomous agent. Provide a plain-English prompt describing the agent's goal and declare the tools it may call. The agent becomes active immediately.
Headers
Accept: application/json Content-Type: application/json X-API-KEY: <api-key>
Request body
| Field | Type | Required | Description |
|---|---|---|---|
Prompt |
string | required | Plain-English description of the agent's goal. Be specific about the trigger condition and desired outcome. |
Tools |
string[] | required | Tool identifiers the agent may call. See Tool Catalog. Apply least privilege — only include tools the agent requires. |
Trigger |
string | optional | Trigger label for this agent, e.g.
"shopify.order.created". Defaults to
"manual" if omitted.
|
Example request
POST https://harness.jheel.io/harness/agents
Content-Type: application/json
X-API-KEY: your_api_key_here
{
"Prompt": "When a new Shopify order is placed, check available stock for each line item in NetSuite. If all items are in stock, confirm the order and send a receipt email via Postmark. If any item is out of stock, flag the order for review.",
"Tools": [
"shopify.orders.read",
"shopify.orders.update",
"netsuite.items.read",
"postmark.email.send"
],
"Trigger": "shopify.order.created"
}
Example response
{
"Success": true,
"Message": "agent created",
"Data": {
"AgentID": "agent-0196a9d1-7b3c-7e4f-a5b6-c7d8e9f0a1b2",
"Status": "active",
"Trigger": "shopify.order.created",
"ToolsAuthorized": [
"shopify.orders.read",
"shopify.orders.update",
"netsuite.items.read",
"postmark.email.send"
],
"Created": "2026-06-14T09:12:00Z",
"Updated": "2026-06-14T09:12:00Z"
}
}
Agents — Get
Retrieves the current configuration and execution history of an agent.
Example request
GET https://harness.jheel.io/harness/agents/agent-0196a9d1-7b3c-7e4f-a5b6-c7d8e9f0a1b2 Accept: application/json X-API-KEY: your_api_key_here
Example response
{
"Success": true,
"Data": {
"AgentID": "agent-0196a9d1-7b3c-7e4f-a5b6-c7d8e9f0a1b2",
"Status": "active",
"Trigger": "shopify.order.created",
"ToolsAuthorized": [
"shopify.orders.read",
"shopify.orders.update",
"netsuite.items.read",
"postmark.email.send"
],
"Executions": [
{
"ExecutionID": "exe-0196aa12-...",
"TriggeredAt": "2026-06-14T11:30:00Z",
"Status": "completed",
"Actions": [
{ "Tool": "shopify.orders.read", "Result": "success" },
{ "Tool": "netsuite.items.read", "Result": "success" },
{ "Tool": "shopify.orders.update", "Result": "success" },
{ "Tool": "postmark.email.send", "Result": "success" }
]
}
],
"Created": "2026-06-14T09:12:00Z",
"Updated": "2026-06-14T11:30:00Z"
}
}
Agents — Edit
Replaces an agent's prompt, tools, and trigger. The agent must be deactivated first via Deactivate Agent. On success the agent is reactivated automatically. Full replacement — partial updates are not supported.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
Prompt |
string | required | Updated agent prompt. |
Tools |
string[] | required | Full replacement tool list. |
Trigger |
string | optional | New trigger label. Unchanged if omitted. |
Example request
PUT https://harness.jheel.io/harness/agents/agent-0196a9d1-...
Content-Type: application/json
X-API-KEY: your_api_key_here
{
"Prompt": "When a new Shopify order is placed, check stock in NetSuite. If in stock, post a journal entry, confirm the order, and send a receipt via Postmark.",
"Tools": [
"shopify.orders.read",
"shopify.orders.update",
"netsuite.items.read",
"netsuite.journal_entries.create",
"postmark.email.send"
]
}
Example response
{
"Success": true,
"Message": "agent updated",
"Data": {
"AgentID": "agent-0196a9d1-7b3c-7e4f-a5b6-c7d8e9f0a1b2",
"Status": "active",
"Trigger": "shopify.order.created",
"ToolsAuthorized": [
"shopify.orders.read",
"shopify.orders.update",
"netsuite.items.read",
"netsuite.journal_entries.create",
"postmark.email.send"
],
"Updated": "2026-06-14T14:00:00Z"
}
}
Agents — Deactivate
Deactivates an agent. The agent stops accepting new triggers. Any execution already in progress is allowed to complete. A deactivated agent can be edited and then reactivated via Edit Agent.
Example request
DELETE https://harness.jheel.io/harness/agents/agent-0196a9d1-7b3c-7e4f-a5b6-c7d8e9f0a1b2 X-API-KEY: your_api_key_here
Example response
{
"Success": true,
"Message": "agent deactivated",
"Data": {
"AgentID": "agent-0196a9d1-7b3c-7e4f-a5b6-c7d8e9f0a1b2",
"Status": "deactivated"
}
}
Agents — Trigger
Submits a trigger to an active agent. The agent run executes
asynchronously — a 202 Accepted is returned
immediately. Use the Trigger Event
Stream to follow execution in real time, or poll the trigger
status via this endpoint using the same TriggerID.
Triggers are idempotent on TriggerID — submitting
the same TriggerID for the same agent twice returns
the existing trigger record without starting a new run.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
TriggerID |
string | required | Your unique identifier for this trigger event, e.g. the Shopify order ID. Used for idempotency. |
AdditionalContext |
object | optional | Arbitrary JSON passed to the agent's planning and tool execution stages. |
Example request
POST https://harness.jheel.io/harness/agents/agent-0196a9d1-.../triggers
Content-Type: application/json
X-API-KEY: your_api_key_here
{
"TriggerID": "shopify-order-98423",
"AdditionalContext": {
"OrderID": "98423",
"CustomerID": "cust-441"
}
}
Example response
{
"Success": true,
"Message": "trigger accepted",
"Data": {
"AgentID": "agent-0196a9d1-7b3c-7e4f-a5b6-c7d8e9f0a1b2",
"TriggerID": "shopify-order-98423",
"Status": "Queued",
"Created": "2026-06-14T12:00:00Z",
"Updated": "2026-06-14T12:00:00Z"
}
}
Queued →
Running → Completed or
Failed. Follow the
event stream for real-time
updates.
Agents — Trigger Event Stream
Opens a Server-Sent Events (SSE) stream for a trigger. Historical
events are replayed first, then live events are pushed as the
agent runs. The stream closes automatically when a terminal event
(AgentTriggerCompleted or
AgentTriggerFailed) is received.
Headers
Accept: text/event-stream X-API-KEY: <api-key>
Example request
GET https://harness.jheel.io/harness/agents/agent-0196a9d1-.../triggers/shopify-order-98423/sink Accept: text/event-stream X-API-KEY: your_api_key_here
Example stream
event: AgentTriggerStarted
data: {"Type":"AgentTriggerStarted","AgentID":"agent-0196a9d1-...","TriggerID":"shopify-order-98423","Timestamp":"2026-06-14T12:00:01Z"}
event: ModelResolved
data: {"Type":"ModelResolved","Timestamp":"2026-06-14T12:00:01Z","Payload":{"Model":"gpt-5.4-mini","Temperature":0.2}}
event: ModelPlanningCompleted
data: {"Type":"ModelPlanningCompleted","Timestamp":"2026-06-14T12:00:03Z","Payload":{"Usage":{"InputTokens":340,"OutputTokens":82}}}
event: ToolCallStarted
data: {"Type":"ToolCallStarted","Timestamp":"2026-06-14T12:00:03Z","Payload":{"Tool":"shopify.orders.read","Status":"Running"}}
event: ToolCallCompleted
data: {"Type":"ToolCallCompleted","Timestamp":"2026-06-14T12:00:04Z","Payload":{"Tool":"shopify.orders.read","Status":"Completed"}}
event: ModelSynthesisCompleted
data: {"Type":"ModelSynthesisCompleted","Timestamp":"2026-06-14T12:00:06Z","Payload":{"Usage":{"InputTokens":610,"OutputTokens":190}}}
event: AgentTriggerCompleted
data: {"Type":"AgentTriggerCompleted","Timestamp":"2026-06-14T12:00:06Z","Payload":{"Status":"Completed","FinalAnswer":"Order confirmed and receipt sent."}}
Event types
| Event | Description |
|---|---|
AgentTriggerStarted |
Execution has begun. |
ModelResolved |
Model configuration confirmed for this run. |
ModelPlanningCompleted |
Planning stage finished; tool selection determined. |
ModelPlanningWarning |
Planning completed with a non-fatal warning. |
ToolCallStarted |
A tool invocation has begun. |
ToolCallCompleted |
A tool invocation finished successfully. |
ToolCallFailed |
A tool invocation failed; execution halted. |
ModelSynthesisCompleted |
Synthesis stage finished; final answer produced. |
AgentTriggerCompleted |
Terminal — run completed successfully. Stream closes. |
AgentTriggerFailed |
Terminal — run failed. Stream closes. |
Python example
import sseclient, requests
url = (
f"{BASE_URL}/harness/agents/{agent_id}"
f"/triggers/{trigger_id}/sink"
)
headers = {"Accept": "text/event-stream", "X-API-KEY": API_KEY}
with requests.get(url, headers=headers, stream=True) as resp:
resp.raise_for_status()
for event in sseclient.SSEClient(resp).events():
print(event.event, event.data)
if event.event in ("AgentTriggerCompleted", "AgentTriggerFailed"):
break
Tool Catalog
Returns all available tools that can be declared in an agent's
Tools array. Apply the principle of least privilege
— only include tools the agent requires.
Example request
GET https://harness.jheel.io/harness/tools Accept: application/json X-API-KEY: your_api_key_here
Example response
{
"Success": true,
"Data": {
"Tools": [
{ "ToolID": "tool-...", "VendorKey": "netsuite", "ToolKey": "netsuite.invoices.read", "Name": "Read Invoices", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "netsuite", "ToolKey": "netsuite.invoices.create", "Name": "Create Invoices", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "netsuite", "ToolKey": "netsuite.journal_entries.read", "Name": "Read Journal Entries", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "netsuite", "ToolKey": "netsuite.journal_entries.create","Name": "Create Journal Entries", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "netsuite", "ToolKey": "netsuite.sales_orders.read", "Name": "Read Sales Orders", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "netsuite", "ToolKey": "netsuite.sales_orders.create", "Name": "Create Sales Orders", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "netsuite", "ToolKey": "netsuite.items.read", "Name": "Read Items", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "shopify", "ToolKey": "shopify.orders.read", "Name": "Read Orders", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "shopify", "ToolKey": "shopify.orders.create", "Name": "Create Orders", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "shopify", "ToolKey": "shopify.orders.update", "Name": "Update Orders", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "shopify", "ToolKey": "shopify.customers.read", "Name": "Read Customers", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "shopify", "ToolKey": "shopify.customers.update", "Name": "Update Customers", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "postmark", "ToolKey": "postmark.email.send", "Name": "Send Email", "Version": "v1" },
{ "ToolID": "tool-...", "VendorKey": "postmark", "ToolKey": "postmark.inbox.read", "Name": "Read Inbox", "Version": "v1" }
]
}
}
Integrations — List
GET /integrations returns the global catalog of
supported vendors. GET /integrations/{key} returns
your tenant's connected instances for that vendor.
Supported vendor keys
| Key | Vendor |
|---|---|
netsuite |
Oracle NetSuite (Token-Based Authentication) |
shopify |
Shopify (Custom App access token) |
postmark |
Postmark (transactional email) |
Example — list masters
GET https://harness.jheel.io/integrations X-API-KEY: your_api_key_here
Example — list tenant connections for Shopify
GET https://harness.jheel.io/integrations/shopify X-API-KEY: your_api_key_here
Example response
{
"Success": true,
"Data": {
"Items": [
{
"ID": "integration-0196ab12-...",
"Key": "shopify",
"Name": "Shopify",
"IntegrationName": "my-shopify-store",
"Status": "active",
"ConfigSummary": {
"ShopDomain": "acme.myshopify.com",
"APIVersion": "2024-07",
"TokenSet": true
},
"CreatedAt": "2026-06-14T10:00:00Z",
"UpdatedAt": "2026-06-14T10:00:00Z"
}
]
}
}
Integrations — Connect
Connects a vendor integration for your tenant. Credentials are
encrypted at rest using AES-256-GCM and never returned in plain
text. The ConfigSummary on read endpoints includes
only non-sensitive metadata.
NetSuite config fields
| Field | Required | Description |
|---|---|---|
AccountID | required | NetSuite account ID. |
ConsumerKey | required | TBA consumer key. |
ConsumerSecret | required | TBA consumer secret. |
TokenKey | required | TBA token key. |
TokenSecret | required | TBA token secret. |
Realm | required | NetSuite account realm, e.g. "ACME_SB1". |
Shopify config fields
| Field | Required | Description |
|---|---|---|
ShopDomain | required | Your Shopify domain, e.g. "acme.myshopify.com". |
AccessToken | required | Custom app access token. |
APIVersion | required | API version, e.g. "2024-07". |
Postmark config fields
| Field | Required | Description |
|---|---|---|
AccountToken | required | Postmark account-level API token. |
ServerToken | required | Postmark server-level API token. |
FromEmail | required | Verified sender address. |
InboundEmail | optional | Inbound email address if inbound processing is enabled. |
ReturnPathDomain | optional | Custom return-path domain for bounce handling. |
Example request — Shopify
POST https://harness.jheel.io/integrations/shopify
Content-Type: application/json
X-API-KEY: your_api_key_here
{
"IntegrationName": "my-shopify-store",
"Config": {
"ShopDomain": "acme.myshopify.com",
"AccessToken": "shpat_abc123...",
"APIVersion": "2024-07"
}
}
Example response
{
"Success": true,
"Message": "integration created",
"Data": {
"ID": "integration-0196ab12-...",
"Key": "shopify",
"Name": "Shopify",
"IntegrationName": "my-shopify-store",
"Status": "active"
}
}
Integrations — Get
Retrieves a single tenant integration with its config summary.
Example request
GET https://harness.jheel.io/integrations/shopify/integration-0196ab12-... X-API-KEY: your_api_key_here
Example response
{
"Success": true,
"Data": {
"ID": "integration-0196ab12-...",
"Key": "shopify",
"Name": "Shopify",
"IntegrationName": "my-shopify-store",
"Status": "active",
"ConfigSummary": {
"ShopDomain": "acme.myshopify.com",
"APIVersion": "2024-07",
"TokenSet": true
},
"CreatedAt": "2026-06-14T10:00:00Z",
"UpdatedAt": "2026-06-14T10:00:00Z"
}
}
Integrations — Update
Replaces the credentials and label for an existing integration. Full replacement — all config fields must be re-supplied.
Example request
PUT https://harness.jheel.io/integrations/shopify/integration-0196ab12-...
Content-Type: application/json
X-API-KEY: your_api_key_here
{
"IntegrationName": "my-shopify-store",
"Config": {
"ShopDomain": "acme.myshopify.com",
"AccessToken": "shpat_new_token...",
"APIVersion": "2025-01"
}
}
Example response
{
"Success": true,
"Message": "integration updated",
"Data": {
"ID": "integration-0196ab12-...",
"Key": "shopify",
"Name": "Shopify",
"IntegrationName": "my-shopify-store",
"Status": "active"
}
}
Integrations — Disable
Disables a tenant integration. Disabled integrations cannot be used by agents at runtime. The configuration is retained and the integration can be re-enabled by updating it.
Example request
DELETE https://harness.jheel.io/integrations/shopify/integration-0196ab12-... X-API-KEY: your_api_key_here
Example response
{
"Success": true,
"Message": "integration disabled",
"Data": {
"ID": "integration-0196ab12-...",
"Status": "disabled"
}
}
Recommended Client Flow
Document extraction — three steps
POST /harness/session
→ { "SessionID": "session-0196a8bc-..." }
POST /harness/session/session-0196a8bc-.../document
→ { "DocumentID": "document-0196a8bd-...", "ExtractedJSON": null }
GET /harness/session/session-0196a8bc-.../document/document-0196a8bd-...
→ poll until ExtractedJSON != null or ErrorMessage != ""
Agent run — three steps
POST /harness/agents
→ { "AgentID": "agent-0196a9d1-..." }
POST /harness/agents/agent-0196a9d1-.../triggers
→ { "TriggerID": "my-event-id", "Status": "Queued" }
GET /harness/agents/agent-0196a9d1-.../triggers/my-event-id/sink
→ stream events until AgentTriggerCompleted or AgentTriggerFailed
Integration setup
GET /integrations → browse supported vendors POST /integrations/shopify → connect credentials GET /harness/tools → confirm tools are available for agents
Notes
-
All API responses are wrapped in a standard envelope. Resource
data is always inside the
Datafield. -
All resource IDs are prefixed strings, e.g.
"session-...","agent-...","document-...". They are not integers. - Document processing is asynchronous. Always poll — never assume immediate results.
- Multiple documents can belong to a single session. Process related documents together for better RAG query context.
-
Agent triggers are idempotent on
TriggerID. Replaying the same trigger ID returns the existing run record without starting a new execution. - Integration credentials are encrypted at rest (AES-256-GCM). Plain-text credentials are never returned after creation.
-
Storage usage (
StorageBytes+VectorBytes) counts against your tenant's 10 GB storage cap by default. -
Agents operate on the principle of least privilege — only
tools explicitly listed in
Toolscan be called at runtime. - All timestamps are UTC ISO 8601.
Questions or integration issues? Get in touch →