A list of ids of emails that precede this email in a conversation thread, as
passed in the References header. If null, this email is not part of a
conversation thread
The message id of the email, as passed in the Message-ID header. This is not
the same as the BotMailRoom email id but rather is an id used by email clients
and servers to identify emails
A list of emails that precede the root email in a conversation thread, as
passed in the References header. If an email is not part of a conversation
thread or is not the root email, this field will be null. Each object is the
same structure as this object
The entire email thread formatted as markdown that can be passed into an LLM
prompt. If the email is not part of a thread or is not the root email, this
will be the same as the prompt property
You can create a signing secret by going to the webhook signing secrets page. When you create your first inbox, BotMailRoom will generate a signing secret for you if you don’t have one yet.
You will only receive a given signing secret once, so make sure to save it in
a secure location.
If you need to regenerate the signing secret, you can do so by going to the secrets page, and clicking the regenerate button next to the signing secret.
When you create an inbox, you must select a signing secret to use from the
dropdown if you have one.
The webhook signing secret allows you to verify that an incoming request to your service is actually coming from BotMailRoom.You can use the python client or typescript client to verify the signature of the webhook:
Copy
from botmailroom import verify_webhook_signatureverify_webhook_signature(signature_header, payload, webhook_secret)
Copy
import { verifyWebhookSignature } from "botmailroom";verifyWebhookSignature(signatureHeader, payload, webhookSecret);
Alternatively, you can manually verify the signature, here’s how the process works:
When BotMailRoom sends a webhook with the email payload, it creates a special signature by:
Taking the webhook payload (as raw bytes)
Using HMAC-SHA256 with your shared secret
Converting the result to a hexadecimal string
Including this signature in the X-Signature header
When you receive the webhook, you need to:
Take the raw payload bytes
Generate the same signature using your signing secret
Compare signatures
To avoid replay attacks, you can also check the timestamp in the payload and ensure it’s within a reasonable time window
If the signatures match, you know:
The request definitely came from BotMailRoom
The data wasn’t modified in transit
Here’s an example of how to verify the signature in Python:
Copy
import hashlibimport hmacfrom datetime import datetime, timedeltadef verify_webhook_signature( signature_header: str, payload_bytes: bytes, webhook_secret: str) -> bool: hash_object = hmac.new( webhook_secret.encode("utf-8"), msg=payload_bytes, digestmod=hashlib.sha256, ) expected_signature = hash_object.hexdigest() signatures_match = hmac.compare_digest(expected_signature, signature_header) if not signatures_match: return False # Optional: check timestamp within some window payload = json.loads(payload_bytes) timestamp = datetime.fromisoformat(payload["timestamp"]) age = datetime.now() - timestamp if age < timedelta(minutes=-1): # timestamp is in the future return False if age > timedelta(minutes=10): # timestamp is too old return False return True
If you don’t have a public url to test with you can use smee or a similar service to create a temporary endpoint. Make sure to put that temporary endpoint in the webhook_url field when creating or updating your inbox. You can also do a one-time send to a specific url in the emails page by clicking on the resend icon in the Webhook Status column.
If your webhook fails to be delivered (any status code outside of 2XX), BotMailRoom will retry an additional 6 times within a 12 hour period (initial interval of 30 seconds, backoff coefficient of 4). After that, you can still view the webhook log and resend it manually in the emails page.