Properties
| Name | Type | Description |
|---|---|---|
| type | object | |
| created_at | string | |
| data | object |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/groundmail-dev/json-schema/groundmail-dev-email-webhook-event-payload-schema.json",
"title": "EmailWebhookEventPayload",
"x-generated": "2026-10-30",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/groundmail-dev-openapi.yaml#/components/schemas/EmailWebhookEventPayload",
"type": "object",
"required": [
"type",
"created_at",
"data"
],
"properties": {
"type": {
"$ref": "#/$defs/EmailWebhookEventType"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"data": {
"type": "object",
"required": [
"email_id",
"to",
"from",
"subject",
"status"
],
"properties": {
"email_id": {
"type": "string"
},
"to": {
"type": "array",
"items": {
"type": "string",
"format": "email"
}
},
"from": {
"type": "string"
},
"subject": {
"type": "string"
},
"status": {
"type": "string"
},
"bounce_reason": {
"type": [
"string",
"null"
]
},
"bounce_type": {
"$ref": "#/$defs/BounceType"
},
"tags": {
"type": "array",
"description": "On every outbound `email.*` event: the email's tags as sent (`[]` when it had none), so you can match an event to your own records without storing the email id first. Not on `email.received`.\n",
"items": {
"$ref": "#/$defs/EmailTag"
}
},
"held_back": {
"type": "array",
"description": "On `email.suppressed` when Groundmail validation held back every recipient.",
"items": {
"$ref": "#/$defs/HeldBackRecipient"
}
},
"test": {
"type": "boolean",
"enum": [
true
],
"description": "Present (and `true`) on simulated events: sends with a test key or to simulator addresses, and `POST /emails/test`. Absent on events from real mail.\n"
},
"tenant": {
"type": "string",
"description": "The `external_id` of the tenant the email was sent for. Present only on tenant email."
},
"stream": {
"$ref": "#/$defs/MailStream"
},
"rcpt_to": {
"type": "string",
"format": "email"
},
"cc": {
"type": "array",
"items": {
"type": "string",
"format": "email"
}
},
"message_id": {
"type": [
"string",
"null"
]
},
"in_reply_to": {
"type": [
"string",
"null"
]
},
"references": {
"type": "array",
"items": {
"type": "string"
}
},
"in_reply_to_email": {
"allOf": [
{
"$ref": "#/$defs/InReplyToEmail"
}
],
"nullable": true,
"description": "On `email.received`: the email you sent through Groundmail that this one replies to, or null when it matches none."
},
"held_reason": {
"type": "string",
"description": "On `email.held`, why the email was held (content scanning, or a pause on the account)."
},
"spam_status": {
"type": [
"string",
"null"
],
"enum": [
"clean",
"suspicious",
"spam"
],
"description": "On `email.received`, the content scanning verdict."
},
"spam_score": {
"type": [
"number",
"null"
],
"description": "Content scanning score: on `email.received` (null when not scanned), and on `email.held` when content scanning held the email."
},
"attachment_count": {
"type": "integer"
},
"attachments": {
"type": "array",
"items": {
"$ref": "#/$defs/ReceivedEmailAttachmentMeta"
}
},
"received_at": {
"type": "string",
"format": "date-time"
}
}
}
},
"$defs": {
"BounceType": {
"type": [
"string",
"null"
],
"enum": [
"hard",
"block"
],
"description": "Why the email bounced. Null when it has not bounced (and for complaints).\n\n- `hard`: the address cannot receive mail (unknown user, disabled mailbox,\n domain with no mail server). The address is added to your suppression list.\n- `block`: the receiving server refused the message because of the sending\n IP's or domain's reputation or policy, for example a blocklist listing or a\n mailbox provider's spam policy. The address is fine and is not suppressed,\n and block bounces do not count toward your bounce rate. You can send to it\n again later.\n\nPresent on `email.bounced` and `email.failed` webhook events and on the email\nobject. Treat unknown future values like `hard`.\n"
},
"EmailTag": {
"type": "object",
"required": [
"name",
"value"
],
"properties": {
"name": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"EmailWebhookEventType": {
"type": "string",
"enum": [
"email.received",
"email.sent",
"email.delivered",
"email.delivery_delayed",
"email.held",
"email.bounced",
"email.complained",
"email.opened",
"email.clicked",
"email.failed",
"email.suppressed",
"email.scheduled"
]
},
"HeldBackRecipient": {
"type": "object",
"required": [
"email",
"reason"
],
"description": "A recipient Groundmail validation held back before sending.",
"properties": {
"email": {
"type": "string",
"description": "The held-back address (trimmed, lowercased)"
},
"reason": {
"type": "string",
"enum": [
"invalid_address",
"no_mail_server",
"previously_bounced",
"mailbox_not_found"
],
"description": "`invalid_address`: the address cannot exist. `no_mail_server`: the domain does not exist or takes no email (no MX or A record, or a null MX). `previously_bounced`: the address hard-bounced (mailbox does not exist) for a Groundmail sender in the last 90 days. `mailbox_not_found`: Groundmail validation already knows the mailbox does not exist. The last two can be turned off per account in Settings → Suppressions.\n"
}
}
},
"InReplyToEmail": {
"type": "object",
"description": "The sent email a received email replies to, as it was when the reply arrived.",
"required": [
"id",
"subject",
"from",
"to",
"sent_at",
"tags",
"tenant"
],
"properties": {
"id": {
"type": "string",
"description": "The sent email's id (`msg_…`). Pass it to `GET /emails/{id}` while it is within data retention."
},
"subject": {
"type": "string"
},
"from": {
"type": "string"
},
"to": {
"type": "array",
"items": {
"type": "string"
}
},
"sent_at": {
"type": "string",
"format": "date-time"
},
"tags": {
"type": "array",
"description": "The email's tags as sent (`[]` when it had none).",
"items": {
"$ref": "#/$defs/EmailTag"
}
},
"tenant": {
"type": [
"string",
"null"
],
"description": "The `external_id` of the tenant it was sent for; null when it was not sent as a tenant."
}
}
},
"MailStream": {
"type": "string",
"enum": [
"transactional",
"product",
"newsletter"
],
"description": "The mail stream an email went out on, from its `category`. Each stream sends\nfrom its own IPs. `newsletter` is for approved accounts only.\n"
},
"ReceivedEmailAttachmentMeta": {
"type": "object",
"required": [
"filename",
"content_type",
"size"
],
"properties": {
"filename": {
"type": "string"
},
"content_type": {
"type": "string"
},
"size": {
"type": "integer"
},
"content_id": {
"type": [
"string",
"null"
]
}
}
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/groundmail-dev-email-webhook-event-payload"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.