Skip to content
Avanet

Run and verify Sophos Email clawback through the API

The Clawback API removes already delivered Sophos Email messages from eligible recipient mailboxes. The safe workflow always has two phases: submit the clawback once, then query GET /messages/{id}/status until every accepted recipient has a terminal result. A 202 response confirms acceptance of the job, not success in the mailbox.

Establish prerequisites and boundaries

Before the first clawback, you need a configured service principal, a valid OAuth2 bearer token, the target tenant UUID, and its discovered regional API host. The Email Management API introduction explains operation families and the safe read test. The planned detailed runbook Authentication and tenant routing for the Sophos Email API brings token, tenant resolution, and regional routing together.

These examples consume already validated variables:

EMAIL_API_HOST="${SOPHOS_API_HOST%/}/email/v1"
SOPHOS_EMAIL_ID="15a7f8ea-691c-4f03-862e-3cefb102818e"

SOPHOS_API_HOST is the regional host discovered for the tenant, not a guessed host. Replace the harmless sample SOPHOS_EMAIL_ID. Every request uses Authorization: Bearer *** and X-Tenant-ID; secrets and complete message data must not enter code, logs, or tickets.

Clawback also requires the relevant PDP/clawback entitlement and a working provider connection. Only messages successfully delivered to eligible mailboxes, and eligible recipients, can be remediated. Post-Delivery Protection in Sophos Fusion covers the connection, UI On demand clawback, and Auto search and remediate. Those UI workflows are not API requests: manual UI clawback is a separate control path, automatic PDP has a separate trigger, and neither replaces API status polling.

Obtain the correct x-sophos-email-id

The {id} path parameter is the value of the X-Sophos-Email-ID MIME header, not the Internet Message-ID, a subject, or an arbitrary UUID. Sophos also documents that this value can be derived from various Email query responses in Live Discover in the Threat Analysis Center. This runbook does not invent a query schema: take x-sophos-email-id from trustworthy message evidence and verify at least the tenant, message, and affected recipients before submission.

Set the value in SOPHOS_EMAIL_ID without whitespace or a line break. For multiple messages, record each ID with its approval and case context; do not build a list from similar subject lines alone.

Claw back one message

The documented single-message endpoint is POST /messages/{id}/clawback. Omitting recipients attempts clawback for all recipients of the message. Use that wider scope only when all recipients belong to the incident. For a controlled pilot, state the target addresses; the specification permits up to 500 entries.

The optional reason is one of malware, phishing, spam, or unwanted. This payload limits the action to two controlled recipients:

{
  "reason": "phishing",
  "recipients": [
    "user1@example.com",
    "user2@example.com"
  ]
}

Submit the POST exactly once and protect the response:

REQUEST_FILE=$(mktemp) || exit 1
RESPONSE_FILE=$(mktemp) || exit 1
trap 'rm -f "$REQUEST_FILE" "$RESPONSE_FILE"' EXIT

cat >"$REQUEST_FILE" <<'JSON'
{
  "reason": "phishing",
  "recipients": ["user1@example.com", "user2@example.com"]
}
JSON

HTTP_STATUS=$(
  printf 'header = "Authorization: Bearer %s"\n' "$SOPHOS_ACCESS_TOKEN" |
  curl --silent --show-error --config - \
    --output "$RESPONSE_FILE" \
    --write-out '%{http_code}' \
    --request POST \
    --header "X-Tenant-ID: $SOPHOS_TENANT_ID" \
    --header 'Accept: application/json' \
    --header 'Content-Type: application/json' \
    --data-binary "@$REQUEST_FILE" \
    "$EMAIL_API_HOST/messages/$SOPHOS_EMAIL_ID/clawback"
)
printf 'Clawback submission returned HTTP %s\n' "$HTTP_STATUS"

Expect 202. The response separates accepted recipients from errors, each with recipient and error. Record acceptance per recipient without exposing the full response. Sophos describes the recipient-constrained single call as atomic: one ineligible selected recipient can fail the whole request. Verify the cause, remove that recipient only when justified, and then submit one deliberate new request.

Claw back multiple messages

For multiple messages, the Sophos guide documents POST /messages/clawback with a messageIds list. Every item is an x-sophos-email-id:

{
  "messageIds": [
    "e4fa988e-76f6-11ee-b962-0242ac120002",
    "eb9df47e-76f6-11ee-b962-0242ac120002",
    "ef790f0276f611eeb9620242ac120002"
  ]
}

The bulk call reduces requests but not verification. Record acceptance and then status for every ID. If only certain recipients of one message are affected, use the single endpoint with recipients; the documented bulk payload has no recipient list.

Poll to a terminal recipient result

For every submitted ID, use the documented GET /messages/{id}/status. The response contains recipient and status under items:

{
  "items": [
    {"recipient": "user1@example.com", "status": "clawbackSuccessful"},
    {"recipient": "user2@example.com", "status": "clawbackFailed"}
  ]
}

clawbackProcessing is intermediate. Record clawbackSuccessful or clawbackFailed as the terminal clawback result for each recipient. The schema can also return delivery states such as accepted, quarantined, deliverySuccessful, or deliveryFailed; do not reinterpret them as a clawback success.

HTTP_STATUS=$(
  printf 'header = "Authorization: Bearer %s"\n' "$SOPHOS_ACCESS_TOKEN" |
  curl --silent --show-error --config - \
    --output "$RESPONSE_FILE" \
    --write-out '%{http_code}' \
    --request GET \
    --header "X-Tenant-ID: $SOPHOS_TENANT_ID" \
    --header 'Accept: application/json' \
    "$EMAIL_API_HOST/messages/$SOPHOS_EMAIL_ID/status"
)
printf 'Clawback status returned HTTP %s\n' "$HTTP_STATUS"

Poll with a bounded interval and jitter while accepted recipients lack a terminal result. Cap attempts and total runtime. At timeout, the outcome is unknown, not failed: do not issue a second POST until a later GET or the Sophos Fusion view establishes whether the first job took effect.

Handle partial results and failures safely

  • Ineligible or already remediated: verify message, domain, delivery, and recipient. Repeated POSTs do not repair an already successful recipient. For an atomically rejected single call, remove ineligible addresses only after that check.
  • Mixed recipient statuses: preserve clawbackSuccessful for successful recipients and investigate clawbackFailed separately. Never report the whole job as successful or process successful recipients again.
  • 400: check ID, JSON, permitted reason, and recipient list. Do not repeat the unchanged request.
  • 401 or 403: renew through OAuth2 or check role, clawback permission, and tenant assignment. Never switch tenant or region experimentally.
  • 404: compare regional host, documented path, and x-sophos-email-id with the evidence.
  • Throttling (429): honor documented retry or rate-limit guidance and slow GET polling with bounded backoff and jitter. Never blindly repeat a POST.
  • Timeout or 5xx: server-side acceptance may have occurred despite no client response. Query the same ID first, bound attempts and duration, and resubmit only after the effect is known.

Acceptance is complete when the submission result, accepted and rejected recipients, and every terminal recipient result are recorded for each requested ID. As a secondary check, inspect the mailbox and Post-Delivery Quarantine in the correct tenant. The API response remains the machine-readable basis for the automation run; UI clawback, automatic PDP, and reports are separate operating paths.