{
  "schema": "aaes/capability-pack/1",
  "provider": "sendgrid",
  "version": "1.0.0",
  "description": "Twilio SendGrid v3 API: send mail, read global and group suppressions, and delete suppression entries from a group or the global list.",
  "notes": "The endpoint host 'sendgrid-api.invalid' is a reserved non-production placeholder (an RFC 2606 reserved TLD): substitute the SendGrid API host for the account — api.sendgrid.com, or api.eu.sendgrid.com for EU regional subusers, according to the reviewed reference pages — before enabling, in every endpoint, in the resource locators and in every egress allowlist entry. The allowlist matches exactly, so all three must be substituted together, and substitution is a required deployment step.\n\nThe API key is created in the Twilio SendGrid App (the retrieved API Keys documentation: Full Access, Custom Access or Billing Access types) and a parent account may act for subusers with the on-behalf-of header — this pack registers no subuser impersonation and the deployment should review whether the stored key is a parent key.\n\nApproval classification: mail.send delivers email to end recipients, so although the vendor operation is a POST-create it is registered as create and send at the minimum R3 tier — send is one of the designated actions requiring human approval — and the request body is unrestricted (up to 1000 personalizations per call, according to the reviewed mail-send reference), so intended limits need a separate enforceable control.\n\nSuppression deletions are registered as delete at the minimum R3 tier: SendGrid's own documentation warns that removing a suppression means email will once again be sent to the previously suppressed address and should be avoided unless the recipient has asked to receive email again, so the effect overrides a recipient's expressed unsubscribe and the tier follows the effect.\n\nDocumented exclusions — this pack does not register: API key management (creating or deleting API keys creates or destroys credentials themselves); adding addresses to the global suppression list (a write that changes what a recipient receives, registered neither here nor elsewhere in this pack); unsubscribe-group administration (creating, updating or deleting suppression groups — deleting a group moves one-click unsubscribers to the global list, per SendGrid's documentation); sender authentication, domain and link-branding configuration (changes what recipients trust as 'from' the customer); scheduled-send cancellation (a separate surface with batch semantics); contacts and marketing-campaigns surfaces; IP pool, warmup and access-management administration; and the Recipients' Data Erasure API — each is a different registration requiring its own review, and none is approximated here.",
  "credential": {
    "secret_ref_id": "secret-ref-sendgrid-api-key",
    "custody": "customer_vault",
    "inject": "header",
    "inject_name": "Authorization",
    "note": "A Twilio SendGrid v3 API key, held in the client's own secret manager. The key is created in the Twilio SendGrid App; according to the reviewed API Keys documentation a key may be Full Access, Custom Access (scoped to a limited set of actions) or Billing Access. The stored material must be the complete Authorization header value (scheme included): 'Bearer ' followed by the API key — SendGrid no longer accepts HTTP Basic authentication for the v3 API, according to the reviewed getting-started guide.\n\nThere is no token-issuance exchange: the key IS the bearer material, so the custody job stores it once and the executor injects it verbatim; renewal means issuing a new key in the app and updating the reference.\n\nExpiry and revocation: SendGrid documents no automatic expiry for API keys — treat a key as valid until revoked; a key can be revoked at any time in the app without changing the account's username and password, and a revoked key fails closed. Note that revoking issuance (not creating new keys) does nothing to already-issued keys: each issued key stays valid until that key itself is revoked.\n\nLeast privilege: issue a Custom Access key with only the scopes these capabilities need (mail send; suppression read and delete) and nothing more — a Full Access key also reaches API-key management, sender authentication and account administration, which this pack deliberately does not register.\n\nExecutor hygiene: the value must live only in executor memory for the lifetime of a call, must never be written to logs, traces or diagnostics, and must not appear in crash dumps; a deployment that cannot meet that bar must not enable the pack."
  },
  "capabilities": [
    {
      "capability_id": "sendgrid.mail.send",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "sendgrid-api.invalid"
      ],
      "endpoint": "https://sendgrid-api.invalid/v3/mail/send",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-sendgrid-api-key",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "create",
        "send"
      ],
      "resource_id": "sendgrid-mail",
      "description": "Send email over the v3 Mail Send endpoint. The vendor operation is a POST-create, but the effect delivers email to end recipients — according to the reviewed reference, up to 1000 personalizations per call, with attachments, templates and an optional send_at schedule up to 72 hours ahead — so the capability is registered as create and send at the minimum R3 tier; send is one of the designated actions requiring human approval.\n\nOn supported AAES-mediated execution paths, irreversible actions require approval by an authorized person; this does not prevent calls through bypass or observation-only paths.\n\nThe request body is unrestricted: the caller names recipients, subjects and content, so intended limits need a separate enforceable control. Recipient addresses are personal data.\n\nThe host is a reserved placeholder: substitute api.sendgrid.com (or api.eu.sendgrid.com for EU regional subusers) before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "sendgrid.suppressions.global.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "sendgrid-api.invalid"
      ],
      "endpoint": "https://sendgrid-api.invalid/v3/suppression/unsubscribes",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-sendgrid-api-key",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "sendgrid-suppressions",
      "description": "Retrieve the paginated collection of globally suppressed email addresses (recipients who unsubscribed from all email), according to the reviewed reference; limit/offset pagination and an email filter are query parameters. Suppressed addresses are personal data. The registered path covers the collection read only.\n\nThe host is a reserved placeholder: substitute the SendGrid API host before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "sendgrid.suppressions.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "sendgrid-api.invalid"
      ],
      "endpoint": "https://sendgrid-api.invalid/v3/asm/suppressions",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-sendgrid-api-key",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "sendgrid-suppressions",
      "description": "Retrieve the collection of all suppressions across unsubscribe groups (email, group id, group name, created_at), according to the reviewed reference. The registered path covers the collection read only; suppressed addresses are personal data.\n\nThe host is a reserved placeholder: substitute the SendGrid API host before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "sendgrid.suppressions.group.delete",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "sendgrid-api.invalid"
      ],
      "endpoint": "https://sendgrid-api.invalid/v3/asm/groups/GROUP_ID/suppressions/EMAIL",
      "method": "DELETE",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-sendgrid-api-key",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "delete"
      ],
      "resource_id": "sendgrid-suppressions",
      "description": "Remove a suppressed address from one unsubscribe group. Registered as delete at the minimum R3 tier: according to the reviewed reference, removing the suppression means email will once again be sent to the previously suppressed address and should be avoided unless the recipient asked to receive email again — the effect overrides a recipient's expressed unsubscribe, and re-adding the address later would be a new suppression, not an undo.\n\nDelete is one of the designated actions requiring human approval.\n\nGROUP_ID and EMAIL are placeholders the deployment binds before enabling, and the host is a reserved placeholder to substitute before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "sendgrid.suppressions.global.delete",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "sendgrid-api.invalid"
      ],
      "endpoint": "https://sendgrid-api.invalid/v3/asm/suppressions/global/EMAIL",
      "method": "DELETE",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-sendgrid-api-key",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "delete"
      ],
      "resource_id": "sendgrid-suppressions",
      "description": "Remove an address from the global suppression list, according to the reviewed reference: after the call, email may be sent to that address again. Registered as delete at the minimum R3 tier — the effect overrides a recipient's unsubscribe-from-all, the widest suppression scope SendGrid has, and re-suppressing later is a new act, not an undo. Delete is one of the designated actions requiring human approval.\n\nOn supported AAES-mediated execution paths, irreversible actions require approval by an authorized person; this does not prevent calls through bypass or observation-only paths. EMAIL is a placeholder the deployment binds before enabling, and the host is a reserved placeholder to substitute before enabling.",
      "requires_review": true
    }
  ],
  "resources": [
    {
      "resource_id": "sendgrid-mail",
      "kind": "api",
      "locator": "https://sendgrid-api.invalid/v3/mail",
      "data_class": "pii",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    },
    {
      "resource_id": "sendgrid-suppressions",
      "kind": "api",
      "locator": "https://sendgrid-api.invalid/v3/suppression",
      "data_class": "pii",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    }
  ],
  "review": {
    "state": "library",
    "date": "2026-09-22",
    "sources": [
      "https://www.twilio.com/docs/sendgrid/api-reference/mail-send/mail-send (retrieved 2026-09-21)",
      "https://www.twilio.com/docs/sendgrid/for-developers/sending-email/api-getting-started (retrieved 2026-09-21)",
      "https://www.twilio.com/docs/sendgrid/api-reference/api-keys (retrieved 2026-09-21)",
      "https://www.twilio.com/docs/sendgrid/api-reference/suppressions-suppressions/retrieve-all-suppressions (retrieved 2026-09-21)",
      "https://www.twilio.com/docs/sendgrid/api-reference/suppressions-global-suppressions/retrieve-all-global-suppressions (retrieved 2026-09-21)",
      "https://www.twilio.com/docs/sendgrid/api-reference/suppressions-suppressions/delete-a-suppression-from-a-suppression-group (retrieved 2026-09-21)",
      "https://www.twilio.com/docs/sendgrid/api-reference/suppressions-global-suppressions/delete-a-global-suppression (retrieved 2026-09-21)",
      "https://www.twilio.com/docs/sendgrid/api-reference/suppressions-unsubscribe-groups/delete-a-suppression-group (retrieved 2026-09-21)"
    ],
    "reviewer_id": "aaes-eng"
  }
}
