Checkpoint Avanan API Patterns
Shape of the Checkpoint Harmony Email (Avanan) `hec_*` tool surface: the thirteen tools and what each reaches, the event/entity split that governs which tool accepts which id, the `responseEnvelope`/`responseData` result shape, `scrollId` pagination, and the auth, regional-routin
Install
npx skills add https://github.com/WYRE-AI/msp-claude-plugins/tree/main/msp-claude-plugins/email-security/checkpoint-avanan/skills/api-patterns
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install wyre-ai-msp-claude-plugins@llmmart
git clone https://github.com/WYRE-AI/msp-claude-plugins.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole wyre-ai/msp-claude-plugins collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Checkpoint Harmony Email API Patterns
Overview
Harmony Email & Collaboration (formerly Avanan) sits alongside Microsoft 365 and Google Workspace via API rather than in the mail path. MSPs use it to review what the detection engines caught, pull the message behind a detection, quarantine or restore mail, and maintain the sender exception lists. Every call in this plugin goes through the Conduit gateway to the Harmony Email Smart API v1.50.
Anti-triggers
avanan_*tool names — a separate legacy Avanan MCP server serves MSP-partner, tenant and licence management underavanan_*names (avanan_create_tenant,avanan_assign_license). None of them reach quarantine, events or exceptions. This vendor's security surface ishec_*only; if you want tenant or licence administration, that is the legacy server, not this plugin.- Detection records and their verdicts — use
avanan-threats. - Finding or acting on the message itself — use
avanan-quarantine. - Sender allow/block entries — use
avanan-exceptions. - Another vendor's auth — "client id and secret against a regional
gateway" describes most of the email-security stack. Mimecast is
mimecast-api-patterns, Proofpoint isproofpoint-api-patterns.
The tool surface
Thirteen tools, all prefixed hec_.
| Tool | Reaches | Required args |
|---|---|---|
hec_query_events |
Detection records, filtered | — |
hec_get_event |
One detection record | eventId |
hec_search_emails |
Mail/SaaS entities, filtered | saas, startDate |
hec_get_email |
One entity, full payload | entityId |
hec_quarantine_events |
Quarantine by event id | eventIds |
hec_restore_events |
Restore by event id | eventIds |
hec_quarantine_emails |
Quarantine by entity id | entityIds |
hec_restore_emails |
Restore by entity id | entityIds |
hec_get_task_status |
Progress of an action | taskId |
hec_list_exceptions |
Whitelist or blacklist | excType |
hec_add_exception |
New list entry | excType |
hec_update_exception |
Edit a list entry | excType, excId |
hec_delete_exception |
Remove a list entry | excType, excId |
There is no policy surface, no reporting or statistics surface, and no incident object. See Capability gaps.
Events and entities are two id namespaces
This is the distinction that determines every tool choice, and getting it wrong produces a not-found error that reads like a stale id.
- An event is a detection: an engine's verdict, with a type, state,
severity and confidence. Its id is
eventId. - An entity is the object that was scanned — usually the email itself,
with subject, sender, recipients, attachments and body. Its id is
entityId.
They are related but not interchangeable. hec_get_event will not accept an
entityId, and hec_quarantine_emails will not accept an eventId. The
bridge is the entityId field carried on the event record: read an event,
take its entityId, then call hec_get_email to see the message the
detection was about.
Both action endpoints exist in parallel for the same reason —
hec_quarantine_events posts event ids, hec_quarantine_emails posts entity
ids, and they resolve to the same underlying mail action. Use whichever id
you already hold rather than converting between them.
Result shape and pagination
Every tool returns the same envelope beneath the formatted text:
{
"responseEnvelope": {
"requestId": "…",
"responseCode": 0,
"responseText": "…",
"recordsNumber": 237,
"scrollId": "…"
},
"responseData": [ … ]
}
recordsNumber is the envelope's own count; when it is absent the page length
is the only figure available. Do not read it as a page size, and do not report
it as a total until the scroll is exhausted.
Pagination is scroll-based, not offset-based. There is no limit, offset,
page or sortBy parameter anywhere in the surface. When a result carries a
scrollId, pass it back as the scrollId argument on the same tool with
the same filters to get the next page; a response with no scrollId is the
last page. Changing the filters mid-scroll invalidates the cursor.
Only hec_query_events and hec_search_emails paginate. The exception,
action and get-by-id tools return complete results.
Auth, region and scopes
Handled for you by the gateway, but the failure modes surface as tool errors, so the shape matters. Full request detail is in references/http-api.md.
Authentication posts clientId and accessKey — not client_secret — and
returns a JWT. Tokens are short-lived (the API reports expiresIn, defaulting
to 1800 seconds) and are refreshed transparently.
Region is decoded from the token, not configured. The auth call always goes
to the EU host; the returned JWT carries a region claim (eu, us, au,
in) that selects the host every subsequent data call uses. A tenant's
credentials therefore work from anywhere — you do not pick a region — but a
credential whose region claim is wrong sends data calls to a host that holds
no data for it.
Scopes are farm:customer pairs, e.g. mt-prod-cp-eu-1:examplecorp. A key
may hold one or several. With one scope the API infers it; with several,
scopes are injected into the request automatically. A key that returns an
empty scope string has no farm association at all and every data call will
come back empty — that is a provisioning problem at Checkpoint, not a query
problem.
Gotchas
- Empty results are the default failure mode. A wrong region, a scopeless
key, or a date range outside retention all return a well-formed response
with zero records rather than an error. Before concluding "no threats
found", confirm the query returned a non-zero
recordsNumberon some broader window. - Errors carry the vendor's text, not an error code. Failures surface as
HEC API error (<status>): <responseText>— the API's own prose fromresponseEnvelope.responseText. There is no stable machine-readable error code catalogue to switch on; read the text. - A 401 is as likely to be a region or scope problem as a bad credential. Rotating a working credential is a common wrong response to it.
- Requests time out at 30 seconds. A wide
hec_search_emailsover a long window can exceed it. Narrow the window rather than retrying identically. - Every date is ISO 8601 and is interpreted as UTC. Passing a local-time string without an offset silently shifts the window.
Capability gaps
The tool surface is smaller than the Harmony Email console. Nothing here reaches:
- Policies — no tool lists, enables, disables or edits a security policy. Policy work is console-only.
- Incidents — there is no incident object, status, assignee or note. Do not attempt to open, update or close one.
- Reporting — no statistics, trend or aggregation tool. Counts must be derived by paging a query.
- Message bodies and attachment content —
hec_get_emailreturns the entity payload including attachment names, sizes and MD5 hashes, but not the file itself.
Related Skills
- Checkpoint Threats — the event surface
- Checkpoint Quarantine — the entity and action surface
- Checkpoint Exceptions — whitelist and blacklist
Files (msp-claude-plugins)
-
references
-
http-api.md 4.2 KB
# Harmony Email Smart API — raw HTTP reference Only needed when calling the Smart API directly. Through the `hec_*` tools all of this is handled for you; it is documented because the failure modes surface in tool errors. ## Authentication ```http POST https://cloudinfra-gw.portal.checkpoint.com/auth/external Content-Type: application/json { "clientId": "<client id>", "accessKey": "<client secret>" } ``` The field is `accessKey`, not `clientSecret` or `client_secret`. ```json { "success": true, "data": { "token": "eyJhbGciOi…", "expiresIn": 1800 } } ``` A response with `success: false` is an auth failure even when the HTTP status is 200 — check the flag, not just the status. `expiresIn` is seconds and defaults to 1800 when absent. The auth call **always** goes to the EU host above, whatever region the tenant lives in. Region selection applies only to data calls. ## Regional hosts The JWT's `region` claim selects the host for every data request: | Claim | Data host | |---|---| | `eu` | `https://cloudinfra-gw.portal.checkpoint.com` | | `us` | `https://cloudinfra-gw-us.portal.checkpoint.com` | | `au` | `https://cloudinfra-gw.ap.portal.checkpoint.com` | | `in` | `https://cloudinfra-gw.in.portal.checkpoint.com` | The EU host is also the default when the claim is missing or unrecognised. Note the inconsistent naming — `-us` is a hostname suffix but `ap` and `in` are subdomains; constructing these by pattern rather than lookup produces a host that does not resolve. ## Required headers ```http Authorization: Bearer <token> x-av-req-id: <fresh UUID per request> Accept: application/json Content-Type: application/json ``` `x-av-req-id` is mandatory on every data request and must be unique per request. Reusing one across calls is a request-tracing problem at the vendor end, not a client-side nicety. ## Scopes ```http GET <data host>/app/hec-api/v1.0/scopes ``` Returns `farm:customer` strings, e.g. `mt-prod-cp-eu-1:examplecorp` (EU) or `mt-prod-cp-1:examplecorp` (US). - One scope: omit `scopes` from requests; the API infers it. - Several scopes: include a `scopes` array inside `requestData` so the API can route the call. - A response of `[""]` means the key has no HEC farm association. Every data call will return empty. This needs Checkpoint support, not a client change. If the detected region returns no scopes, probing the other regional hosts with the same token is the diagnostic — a token whose `region` claim disagrees with where the tenant actually lives is a known provisioning state. ## Endpoint map All data paths are prefixed `/app/hec-api`. | Operation | Method + path | |---|---| | Query events | `POST /v1.0/event/query` | | Get event | `GET /v1.0/event/{eventId}` | | Search entities | `POST /v1.0/search/query` | | Get entity | `GET /v1.0/search/entity/{entityId}` | | Event action | `POST /v1.0/action/event` | | Entity action | `POST /v1.0/action/entity` | | Task status | `GET /v1.0/task/{taskId}` | | List exceptions | `GET /v1.0/exceptions/{whitelist\|blacklist}` | | Add exception | `POST /v1.0/exceptions/{whitelist\|blacklist}` | | Update exception | `PUT /v1.0/exceptions/{whitelist\|blacklist}/{excId}` | | Delete exception | `POST /v1.0/exceptions/{whitelist\|blacklist}/delete/{excId}` | Deleting an exception is a **POST to a `/delete/` path**, not an HTTP DELETE. Both action endpoints take the operation as a field in the body — `eventActionName` or `entityActionName`, valued `quarantine` or `restore` — rather than encoding it in the path. ## Request body envelope Every POST and PUT wraps its payload in `requestData`: ```json { "requestData": { "eventIds": ["…"], "eventActionName": "quarantine" } } ``` ## Responses and errors ```json { "responseEnvelope": { "requestId": "…", "responseCode": 0, "responseText": "…", "recordsNumber": 237, "scrollId": "…" }, "responseData": [ … ] } ``` Errors are reported as `responseEnvelope.responseText` alongside a non-2xx status. There is no `error.code` object and no documented machine-readable code catalogue. A 401 invalidates the cached token; re-authenticate before retrying, and consider region and scope before assuming the credential itself is wrong. Timeouts in use: 30s for auth and data calls, 10s for the scopes lookup.
-
-
SKILL.md 8.1 KB
--- name: "Checkpoint Avanan API Patterns" description: > Shape of the Checkpoint Harmony Email (Avanan) `hec_*` tool surface: the thirteen tools and what each reaches, the event/entity split that governs which tool accepts which id, the `responseEnvelope`/`responseData` result shape, `scrollId` pagination, and the auth, regional-routing and farm-scope behaviour behind every call. when_to_use: >- When orienting in the Harmony Email tool surface, choosing between the event and entity tools, paging a large result set, or reading an authentication, region or scope failure. Use when: checkpoint api, avanan api, hec api, harmony email api, checkpoint authentication, checkpoint region, hec scopes, scrollId, avanan pagination, or an `HEC API error (...)` message. --- # Checkpoint Harmony Email API Patterns ## Overview Harmony Email & Collaboration (formerly Avanan) sits alongside Microsoft 365 and Google Workspace via API rather than in the mail path. MSPs use it to review what the detection engines caught, pull the message behind a detection, quarantine or restore mail, and maintain the sender exception lists. Every call in this plugin goes through the Conduit gateway to the Harmony Email Smart API v1.50. ## Anti-triggers - **`avanan_*` tool names** — a separate legacy Avanan MCP server serves MSP-partner, tenant and licence management under `avanan_*` names (`avanan_create_tenant`, `avanan_assign_license`). None of them reach quarantine, events or exceptions. This vendor's security surface is `hec_*` only; if you want tenant or licence administration, that is the legacy server, not this plugin. - **Detection records and their verdicts** — use `avanan-threats`. - **Finding or acting on the message itself** — use `avanan-quarantine`. - **Sender allow/block entries** — use `avanan-exceptions`. - **Another vendor's auth** — "client id and secret against a regional gateway" describes most of the email-security stack. Mimecast is `mimecast-api-patterns`, Proofpoint is `proofpoint-api-patterns`. ## The tool surface Thirteen tools, all prefixed `hec_`. | Tool | Reaches | Required args | |---|---|---| | `hec_query_events` | Detection records, filtered | — | | `hec_get_event` | One detection record | `eventId` | | `hec_search_emails` | Mail/SaaS entities, filtered | `saas`, `startDate` | | `hec_get_email` | One entity, full payload | `entityId` | | `hec_quarantine_events` | Quarantine by event id | `eventIds` | | `hec_restore_events` | Restore by event id | `eventIds` | | `hec_quarantine_emails` | Quarantine by entity id | `entityIds` | | `hec_restore_emails` | Restore by entity id | `entityIds` | | `hec_get_task_status` | Progress of an action | `taskId` | | `hec_list_exceptions` | Whitelist or blacklist | `excType` | | `hec_add_exception` | New list entry | `excType` | | `hec_update_exception` | Edit a list entry | `excType`, `excId` | | `hec_delete_exception` | Remove a list entry | `excType`, `excId` | There is no policy surface, no reporting or statistics surface, and no incident object. See [Capability gaps](#capability-gaps). ## Events and entities are two id namespaces This is the distinction that determines every tool choice, and getting it wrong produces a not-found error that reads like a stale id. - An **event** is a detection: an engine's verdict, with a type, state, severity and confidence. Its id is `eventId`. - An **entity** is the object that was scanned — usually the email itself, with subject, sender, recipients, attachments and body. Its id is `entityId`. They are related but not interchangeable. `hec_get_event` will not accept an `entityId`, and `hec_quarantine_emails` will not accept an `eventId`. The bridge is the `entityId` field carried **on the event record**: read an event, take its `entityId`, then call `hec_get_email` to see the message the detection was about. Both action endpoints exist in parallel for the same reason — `hec_quarantine_events` posts event ids, `hec_quarantine_emails` posts entity ids, and they resolve to the same underlying mail action. Use whichever id you already hold rather than converting between them. ## Result shape and pagination Every tool returns the same envelope beneath the formatted text: ```json { "responseEnvelope": { "requestId": "…", "responseCode": 0, "responseText": "…", "recordsNumber": 237, "scrollId": "…" }, "responseData": [ … ] } ``` `recordsNumber` is the envelope's own count; when it is absent the page length is the only figure available. Do not read it as a page size, and do not report it as a total until the scroll is exhausted. Pagination is **scroll-based, not offset-based**. There is no `limit`, `offset`, `page` or `sortBy` parameter anywhere in the surface. When a result carries a `scrollId`, pass it back as the `scrollId` argument on the *same* tool with the *same* filters to get the next page; a response with no `scrollId` is the last page. Changing the filters mid-scroll invalidates the cursor. Only `hec_query_events` and `hec_search_emails` paginate. The exception, action and get-by-id tools return complete results. ## Auth, region and scopes Handled for you by the gateway, but the failure modes surface as tool errors, so the shape matters. Full request detail is in [references/http-api.md](references/http-api.md). **Authentication** posts `clientId` and `accessKey` — not `client_secret` — and returns a JWT. Tokens are short-lived (the API reports `expiresIn`, defaulting to 1800 seconds) and are refreshed transparently. **Region is decoded from the token, not configured.** The auth call always goes to the EU host; the returned JWT carries a `region` claim (`eu`, `us`, `au`, `in`) that selects the host every subsequent data call uses. A tenant's credentials therefore work from anywhere — you do not pick a region — but a credential whose region claim is wrong sends data calls to a host that holds no data for it. **Scopes are `farm:customer` pairs**, e.g. `mt-prod-cp-eu-1:examplecorp`. A key may hold one or several. With one scope the API infers it; with several, scopes are injected into the request automatically. A key that returns an empty scope string has no farm association at all and every data call will come back empty — that is a provisioning problem at Checkpoint, not a query problem. ## Gotchas - **Empty results are the default failure mode.** A wrong region, a scopeless key, or a date range outside retention all return a well-formed response with zero records rather than an error. Before concluding "no threats found", confirm the query returned a non-zero `recordsNumber` on some broader window. - **Errors carry the vendor's text, not an error code.** Failures surface as `HEC API error (<status>): <responseText>` — the API's own prose from `responseEnvelope.responseText`. There is no stable machine-readable error code catalogue to switch on; read the text. - **A 401 is as likely to be a region or scope problem as a bad credential.** Rotating a working credential is a common wrong response to it. - **Requests time out at 30 seconds.** A wide `hec_search_emails` over a long window can exceed it. Narrow the window rather than retrying identically. - **Every date is ISO 8601 and is interpreted as UTC.** Passing a local-time string without an offset silently shifts the window. ## Capability gaps The tool surface is smaller than the Harmony Email console. Nothing here reaches: - **Policies** — no tool lists, enables, disables or edits a security policy. Policy work is console-only. - **Incidents** — there is no incident object, status, assignee or note. Do not attempt to open, update or close one. - **Reporting** — no statistics, trend or aggregation tool. Counts must be derived by paging a query. - **Message bodies and attachment content** — `hec_get_email` returns the entity payload including attachment names, sizes and MD5 hashes, but not the file itself. ## Related Skills - [Checkpoint Threats](../threats/SKILL.md) — the event surface - [Checkpoint Quarantine](../quarantine/SKILL.md) — the entity and action surface - [Checkpoint Exceptions](../exceptions/SKILL.md) — whitelist and blacklist
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.