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.

Ready to build? Create a free account to get your API key and start making calls in minutes.

Workflow overview

For document extraction, the standard flow is:

  1. Create a session — a container for one or more related documents.
  2. Upload one or more documents to the session.
  3. Poll the document endpoint until ExtractedJSON is populated or ErrorMessage is non-empty.
Document processing is asynchronous. Always poll for results — do not assume 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.

Don't have an API key yet? Sign up for free — your first key is generated instantly on account creation.

API Keys — List

Returns all API keys for the authenticated user. Requires a JWT bearer token from the login endpoint.

GET /api-keys

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.

POST /api-keys

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"
  }
}
The 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.

DELETE /api-keys/{id}

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.

POST /harness/session

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.

GET /harness/session/{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).

POST /harness/session/{id}/document

Headers

Accept: application/json
X-API-KEY: <api-key>
Do not set 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.

GET /harness/session/{id}/document/{docid}

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."
A polling interval of 2–5 seconds is recommended. Most documents complete within 3–8 seconds. Complex multi-page documents may take longer.

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.

POST /harness/rag/query

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.

POST /harness/agents

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.

GET /harness/agents/{id}

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.

PUT /harness/agents/{id}

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.

DELETE /harness/agents/{id}

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.

POST /harness/agents/{id}/triggers

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"
  }
}
Trigger status progresses through: QueuedRunningCompleted 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.

GET /harness/agents/{id}/triggers/{triggerId}/sink

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.

GET /harness/tools

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" }
    ]
  }
}
Additional integrations are in active development. Contact us to request a specific tool or integration.

Integrations — List

GET /integrations returns the global catalog of supported vendors. GET /integrations/{key} returns your tenant's connected instances for that vendor.

GET /integrations
GET /integrations/{key}

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.

POST /integrations/{key}

NetSuite config fields

Field Required Description
AccountIDrequiredNetSuite account ID.
ConsumerKeyrequiredTBA consumer key.
ConsumerSecretrequiredTBA consumer secret.
TokenKeyrequiredTBA token key.
TokenSecretrequiredTBA token secret.
RealmrequiredNetSuite account realm, e.g. "ACME_SB1".

Shopify config fields

Field Required Description
ShopDomainrequiredYour Shopify domain, e.g. "acme.myshopify.com".
AccessTokenrequiredCustom app access token.
APIVersionrequiredAPI version, e.g. "2024-07".

Postmark config fields

Field Required Description
AccountTokenrequiredPostmark account-level API token.
ServerTokenrequiredPostmark server-level API token.
FromEmailrequiredVerified sender address.
InboundEmailoptionalInbound email address if inbound processing is enabled.
ReturnPathDomainoptionalCustom 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.

GET /integrations/{key}/{id}

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.

PUT /integrations/{key}/{id}

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.

DELETE /integrations/{key}/{id}

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 Data field.
  • 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 Tools can be called at runtime.
  • All timestamps are UTC ISO 8601.

Questions or integration issues? Get in touch →

Everything clear? Start building. Your API keys and session history live in your dashboard. Access them anytime.