ActiveTechapimiddlewarezohokrakenwebhooks

Hermes

Integration middleware for Zoho, Kraken, and third parties via API

What is Hermes

Hermes is the integration middleware that connects our applications to external services such as Zoho and Kraken.

Hermes acts as a bridge between your applications and third parties. It handles OAuth authentication, forwards REST and GraphQL requests, and routes inbound webhooks to subscribed apps.

What is it for?

  • Authenticated proxy to Zoho CRM, Books, and WorkDrive
  • GraphQL relay to Kraken with no embedded queries
  • Inbound Zoho webhook reception and HMAC-signed delivery
  • Centralised OAuth tokens and HTTP retries

Production base URL:https://hermes.oees.tech/api/v1

For deployment, environment variables, and operations, see the repository: https://github.com/oees/hermes

Architecture

Hermes exposes a FastAPI API and a Celery worker sharing PostgreSQL for credentials, API clients, and webhook subscriptions.

Outgoing calls

Your App ──(X-API-Key)──▶ Hermes ──(OAuth / JWT)──▶ Third party
                              │
                              ▼
                    ┌──────────────────────┐
                    │  PostgreSQL (DO)     │
                    └──────────────────────┘

Inbound webhooks

Zoho ──webhook──▶ Hermes ──route by subscription_name──▶ Your App(s)
                              │
                              ▼
                         Celery worker
                              │
                              ▼
                    POST + HMAC signature

Main components

  • FastAPI API — HTTP endpoints, CORS, API key validation
  • Celery worker — Asynchronous webhook delivery with retries
  • PostgreSQL — OAuth credentials, API clients, subscriptions
  • Integrations — REST/GraphQL clients in app/integrations/

Authentication

Protected endpoints require a valid API key. Hermes handles third-party authentication separately.

API key (caller → Hermes)

Include this header on every request to protected endpoints:

X-API-Key: hms_live_{32_hex}

Generate an API key

python -m app.cli.commands create-api-key my-app

Errors

An invalid or missing API key returns HTTP 401 — Invalid or missing API key.

Hermes → third parties

  • Zoho CRM, Books, WorkDrive: OAuth2 refresh token → access token
  • Kraken: client credentials → JWT via auth server

Integrations

Hermes supports four integration families. Each exposes setup and proxy (or relay) endpoints under /api/v1/.

Zoho CRM

REST proxy to API v8 and read-only COQL queries.

  • POST /zoho/setup — store OAuth tokens
  • POST /zoho/proxy — REST proxy (GET/POST/PUT/PATCH/DELETE)
  • POST /zoho/query — COQL queries

Zoho Books

Accounting REST proxy; Hermes injects organization_id automatically.

  • POST /zoho-books/setup — bootstrap with refresh_token
  • POST /zoho-books/proxy — Books v3 REST proxy

Zoho WorkDrive

REST proxy, downloads, and file uploads (max 250 MB).

  • POST /zoho-workdrive/setup — bootstrap with refresh_token
  • POST /zoho-workdrive/proxy — WorkDrive REST proxy
  • POST /zoho-workdrive/upload — multipart upload

Kraken

Pure GraphQL relay: the caller sends query, variables, and operationName.

  • POST /kraken/graphql — relay with no embedded queries

API reference

All paths are relative to https://hermes.oees.tech/api/v1. OpenAPI (/docs) is only available when APP_DEBUG=true.

MethodPathAuthDescription
GET/healthNoHealth check (DB + zoho_configured)
POST/zoho/setupYesConfigure OAuth CRM tokens
POST/zoho/proxyYesProxy to Zoho CRM API
POST/zoho/queryYesCOQL read-only queries
POST/zoho-books/setupYesConfigure Zoho Books OAuth
POST/zoho-books/proxyYesProxy to Zoho Books API
POST/zoho-workdrive/setupYesConfigure WorkDrive OAuth
POST/zoho-workdrive/proxyYesProxy to WorkDrive API
POST/zoho-workdrive/uploadYesUpload file (multipart, max 250 MB)
POST/kraken/graphqlYesRelay GraphQL to Kraken
POST/webhooks/zohoNoZoho webhook receiver
POST/webhooks/webhook-subscriptionsYesCreate webhook subscription
DELETE/webhooks/webhook-subscriptions/{id}YesDelete subscription (owner only)

Webhooks

Hermes receives webhooks from Zoho and asynchronously forwards them to subscribed apps, signed with HMAC-SHA256.

Flow

  1. Zoho sends POST /api/v1/webhooks/zoho with subscription_name in the body
  2. Hermes finds active subscriptions whose name matches
  3. Celery enqueues delivery to each target_url
  4. Your app verifies X-Hermes-Signature with the subscription secret

Routing by subscription_name

Zoho may send one name or several. Supported formats:

  • Simple string: "my-app"
  • Bracketed string: "[app-a, app-b]"
  • JSON array: ["app-a", "app-b"]

Create subscription

The name field is the routing key. module and events are metadata only; Hermes does not filter inbound webhooks by them.

Payload your app receives

  • integration, module, event, data, timestamp, subscription_id
  • Headers: X-Hermes-Signature, X-Hermes-Subscription-Id

Verify signature

Compare the HMAC-SHA256 of the JSON body with the header:

X-Hermes-Signature: sha256={hex}

Retries

Up to 5 retries with exponential backoff (10s, 20s, 40s, 80s, 160s).

Quick start

Minimal examples to verify connectivity and start integrating. Replace hms_live_xxx with your API key.

Health check

curl https://hermes.oees.tech/api/v1/health

Zoho CRM proxy

curl -X POST https://hermes.oees.tech/api/v1/zoho/proxy \
  -H "X-API-Key: hms_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "method": "GET",
    "endpoint": "/Leads/12345"
  }'

Create webhook subscription

curl -X POST https://hermes.oees.tech/api/v1/webhooks/webhook-subscriptions \
  -H "X-API-Key: hms_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-app",
    "integration": "zoho",
    "module": "Leads",
    "events": ["create", "edit"],
    "target_url": "https://my-app.com/webhooks"
  }'