git:20260728.b7e78fc to git:20260806.a261342

136 added, 238 removed. Audit A to A.

---
name: "Checkpoint Avanan API Patterns"
description: >
- Checkpoint Harmony Email & Collaboration (Avanan) API fundamentals:
- OAuth2 client-credentials authentication, regional base URLs, request
- and pagination patterns, rate limiting, error handling, and performance
- optimization for the Harmony Email API.
+ 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 authenticating to or calling the Checkpoint Harmony Email API directly
- or through MCP tools. Use when: checkpoint api, avanan api, checkpoint
- authentication, checkpoint oauth, avanan oauth, checkpoint rate limit,
- checkpoint pagination, avanan api error, checkpoint rest api, or infinity
- portal api.
+ 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
- The Checkpoint Harmony Email & Collaboration (Avanan) API provides programmatic access to email security operations including quarantine management, threat detection, policy configuration, and incident management. This skill covers authentication, request patterns, pagination, rate limiting, error handling, and performance optimization.
-
- ## Authentication
-
- ### OAuth2 Client Credentials Flow
-
- Checkpoint Harmony Email uses OAuth2 client credentials for API authentication:
-
- **Step 1: Obtain Access Token**
-
- ```http
- POST https://cloudinfra-gw.portal.checkpoint.com/auth/external
- Content-Type: application/json
-
- {
- "clientId": "YOUR_CLIENT_ID",
- "accessKey": "YOUR_CLIENT_SECRET"
- }
- ```
-
- **Response:**
- ```json
- {
- "data": {
- "token": "eyJhbGciOiJSUzI1NiIs...",
- "expiresIn": 3600,
- "csrfToken": "abc123..."
- }
- }
- ```
-
- **Step 2: Use Token in Subsequent Requests**
-
- ```http
- GET https://cloudinfra-gw.portal.checkpoint.com/app/hec-api/v1.0/quarantine
- Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
- Content-Type: application/json
- ```
-
- ### Token Management
-
- | Field | Description |
- |-------|-------------|
- | `token` | JWT bearer token for API requests |
- | `expiresIn` | Token lifetime in seconds (typically 3600 = 1 hour) |
- | `csrfToken` | CSRF token for state-changing operations |
-
- Refresh the token proactively — 5 minutes before `expiresIn` elapses — rather than waiting for a 401. See [references/client-examples.md](references/client-examples.md) for a token-refresh client implementation.
-
- ### Environment Variables
-
- ```bash
- export CHECKPOINT_CLIENT_ID="your-client-id"
- export CHECKPOINT_CLIENT_SECRET="your-client-secret"
- export CHECKPOINT_AVANAN_MCP_URL="https://checkpoint-avanan-mcp.wyre.workers.dev/mcp"
- ```
-
- ## Base URLs
-
- ### API Gateway
-
- | Environment | Base URL |
- |-------------|----------|
- | **Production (US)** | `https://cloudinfra-gw.portal.checkpoint.com` |
- | **Production (EU)** | `https://cloudinfra-gw-eu.portal.checkpoint.com` |
- | **Production (AP)** | `https://cloudinfra-gw-ap.portal.checkpoint.com` |
-
- ### API Paths
-
- | Service | Path Prefix | Description |
- |---------|-------------|-------------|
- | **Authentication** | `/auth/external` | OAuth2 token endpoint |
- | **Email Security** | `/app/hec-api/v1.0` | Harmony Email & Collaboration API |
- | **Quarantine** | `/app/hec-api/v1.0/quarantine` | Quarantine operations |
- | **Threats** | `/app/hec-api/v1.0/threats` | Threat detection data |
- | **Policies** | `/app/hec-api/v1.0/policies` | Policy management |
- | **Incidents** | `/app/hec-api/v1.0/incidents` | Incident management |
-
- ### Region Detection
-
- The API region depends on where the tenant was provisioned. Use the portal URL to determine the correct API gateway:
-
- | Portal URL | API Gateway |
- |-----------|-------------|
- | `portal.checkpoint.com` | `cloudinfra-gw.portal.checkpoint.com` |
- | `portal.checkpoint.com` (EU data) | `cloudinfra-gw-eu.portal.checkpoint.com` |
- | `portal.checkpoint.com` (AP data) | `cloudinfra-gw-ap.portal.checkpoint.com` |
-
- ## Request Patterns
-
- ### Standard GET Request
-
- ```http
- GET /app/hec-api/v1.0/quarantine?startDate=2024-02-01&endDate=2024-02-15&limit=50
- Authorization: Bearer <token>
- Content-Type: application/json
- ```
-
- ### Standard POST Request
-
- ```http
- POST /app/hec-api/v1.0/quarantine/release
- Authorization: Bearer <token>
- Content-Type: application/json
-
- {
- "entityIds": ["qe-abc123", "qe-def456"],
- "releaseToRecipients": true,
- "addToAllowList": false
- }
- ```
-
- ### Query Parameters
-
- | Parameter | Type | Description | Default |
- |-----------|------|-------------|---------|
- | `startDate` | string (ISO 8601) | Start of date range filter | Required for list operations |
- | `endDate` | string (ISO 8601) | End of date range filter | Required for list operations |
- | `limit` | int | Maximum results per page | 50 |
- | `offset` | int | Number of results to skip | 0 |
- | `sortBy` | string | Field to sort by | `detectedDate` |
- | `sortOrder` | string | ASC or DESC | DESC |
+ 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.
- ## Pagination
+ ## Anti-triggers
- ### Offset-Based Pagination
+ - **`avanan_*` tool names** — a separate `avanan-legacy-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 `checkpoint-avanan-threats`.
+ - **Finding or acting on the message itself** — use
+ `checkpoint-avanan-quarantine`.
+ - **Sender allow/block entries** — use `checkpoint-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`.
- ```http
- GET /app/hec-api/v1.0/threats?startDate=2024-02-01&endDate=2024-02-15&limit=50&offset=0
- ```
+ ## The tool surface
- **Response:**
- ```json
- {
- "data": [...],
- "pagination": {
- "total": 237,
- "limit": 50,
- "offset": 0,
- "hasMore": true
- }
- }
- ```
+ Thirteen tools, all prefixed `hec_`.
- Loop on `pagination.hasMore`, incrementing `offset` by `limit` each pass, until the API reports no more pages. See [references/client-examples.md](references/client-examples.md) for a full pagination helper.
+ | 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` |
- ### Pagination Limits
+ There is no policy surface, no reporting or statistics surface, and no
+ incident object. See [Capability gaps](#capability-gaps).
- | Parameter | Maximum | Notes |
- |-----------|---------|-------|
- | `limit` | 200 | Results per page |
- | Date range | 90 days | Maximum date range per query |
- | Total results | 10,000 | Maximum results per query (paginate within this) |
+ ## Events and entities are two id namespaces
- ## Rate Limiting
+ This is the distinction that determines every tool choice, and getting it
+ wrong produces a not-found error that reads like a stale id.
- ### Rate Limit Thresholds
+ - 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`.
- | Limit Type | Value | Scope |
- |-----------|-------|-------|
- | **Requests per minute** | 60 | Per API key |
- | **Requests per hour** | 1,000 | Per API key |
- | **Concurrent requests** | 5 | Per API key |
- | **Bulk operations per request** | 100 | Per batch operation |
+ 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.
- ### Rate Limit Response
+ 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.
- When rate limited, the API returns HTTP 429:
+ ## Result shape and pagination
- ```http
- HTTP/1.1 429 Too Many Requests
- Retry-After: 30
- X-RateLimit-Limit: 60
- X-RateLimit-Remaining: 0
- X-RateLimit-Reset: 1708012800
- ```
+ Every tool returns the same envelope beneath the formatted text:
```json
{
- "error": {
- "code": "RATE_LIMIT_EXCEEDED",
- "message": "Rate limit exceeded. Retry after 30 seconds."
- }
+ "responseEnvelope": {
+ "requestId": "…",
+ "responseCode": 0,
+ "responseText": "…",
+ "recordsNumber": 237,
+ "scrollId": "…"
+ },
+ "responseData": [ … ]
}
```
- ### Rate Limit Headers
-
- | Header | Description |
- |--------|-------------|
- | `X-RateLimit-Limit` | Maximum requests per window |
- | `X-RateLimit-Remaining` | Remaining requests in current window |
- | `X-RateLimit-Reset` | Unix timestamp when the window resets |
- | `Retry-After` | Seconds to wait before retrying (on 429) |
-
- ### Retry Strategy
-
- On 429, wait `Retry-After` seconds plus jitter before retrying. On 401, refresh the token and retry once. On other failures, use exponential backoff with jitter. See [references/client-examples.md](references/client-examples.md) for a full retry-wrapper implementation.
-
- ## Error Handling
-
- ### HTTP Status Codes
-
- | Code | Meaning | Action |
- |------|---------|--------|
- | 200 | Success | Process response |
- | 201 | Created | Entity created successfully |
- | 204 | No Content | Operation succeeded, no body |
- | 400 | Bad Request | Check request format/values |
- | 401 | Unauthorized | Refresh token or check credentials |
- | 403 | Forbidden | Check API key permissions/scope |
- | 404 | Not Found | Entity doesn't exist |
- | 409 | Conflict | Resource conflict (e.g., already released) |
- | 422 | Unprocessable Entity | Validation failed |
- | 429 | Rate Limited | Implement backoff with Retry-After |
- | 500 | Server Error | Retry with exponential backoff |
- | 503 | Service Unavailable | Temporary outage, retry later |
-
- ### Error Response Format
+ `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.
- Errors return an `error` object with `code`, `message`, and (for validation failures) a `details` array naming the offending fields. See [references/errors.md](references/errors.md) for the full response example and the common error-code table.
+ 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.
- ## Performance Optimization
+ Only `hec_query_events` and `hec_search_emails` paginate. The exception,
+ action and get-by-id tools return complete results.
- ### Minimize API Calls
+ ## Auth, region and scopes
- Fetch related data in one request using the `include` parameter (e.g., `include: ['iocs', 'timeline', 'relatedEmails']`) instead of issuing separate calls per related resource.
+ 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).
- ### Parallelize Independent Requests
+ **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.
- Issue independent list calls (quarantine, threats, incidents) concurrently rather than sequentially. See [references/client-examples.md](references/client-examples.md) for both patterns as code.
+ **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.
- ### Use Appropriate Page Sizes
+ **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.
- - Small page size (10-25) for interactive UI queries
- - Medium page size (50-100) for batch processing
- - Maximum page size (200) for data export operations
+ ## Gotchas
- ### Cache Static Data
+ - **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.
- Cache slowly-changing data to reduce API calls:
- - Policy configurations (refresh every 15 minutes)
- - Allow/block lists (refresh every 5 minutes)
- - Tenant settings (refresh every 30 minutes)
+ ## Capability gaps
- ## Best Practices
+ The tool surface is smaller than the Harmony Email console. Nothing here
+ reaches:
- 1. **Refresh tokens proactively** - Refresh 5 minutes before expiry, not after failure
- 2. **Use the correct regional endpoint** - Mismatched regions return auth errors
- 3. **Implement exponential backoff** - Handle 429 and 5xx errors gracefully
- 4. **Monitor rate limit headers** - Track remaining requests to avoid hitting limits
- 5. **Use bulk operations** - Batch quarantine release/delete instead of individual calls
- 6. **Paginate large results** - Never fetch unbounded result sets
- 7. **Cache reference data** - Reduce calls for policies, lists, and settings
- 8. **Validate before sending** - Check required fields and date ranges client-side
- 9. **Handle token expiry gracefully** - 401 errors should trigger automatic re-auth
+ - **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 Quarantine](../quarantine/SKILL.md) - Quarantine management
- - [Checkpoint Threats](../threats/SKILL.md) - Threat detection and analysis
- - [Checkpoint Policies](../policies/SKILL.md) - Policy management
- - [Checkpoint Incidents](../incidents/SKILL.md) - Incident investigation
+ - [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