SDK
Webhooks
Get notified when a customer's agent changes state, instead of polling. Subscribe a URL, and Maritime POSTs a signed JSON body on every lifecycle event.
Events
Each delivery carries the agent's external_id, so you route it to your own customer without a lookup.
| Event | Fires when |
|---|---|
| agent.deployed | the agent finished deploying and is ready |
| agent.error | the agent entered an error state |
| agent.sleeping | the agent auto-slept after going idle |
| agent.woken | a sleeping agent was woken |
| agent.restarted | the agent was restarted |
| agent.stopped | the agent was stopped |
Subscribe
Create a subscription once. The signing secret is returned once. Store it to verify deliveries.
const hook = await maritime.webhooks.create({
url: 'https://your-app.com/maritime/webhook',
events: ['agent.error', 'agent.deployed'], // omit for all events
})
// hook.secret is shown once. Store it to verify signatures.
await maritime.webhooks.test(hook.id) // deliver a synthetic pingVerify the signature
Every delivery is signed. Verify the X-Maritime-Signature header (an HMAC-SHA256 of the raw body with your secret) before trusting the payload. Fail closed if the secret is unset. Never verify against an empty key.
your webhook handler
import crypto from 'node:crypto'
const SECRET = process.env.MARITIME_WEBHOOK_SECRET
if (!SECRET) throw new Error('MARITIME_WEBHOOK_SECRET is required')
export async function POST(req: Request) {
const raw = await req.text() // exact bytes: the signature is over these
const expected = 'sha256=' + crypto.createHmac('sha256', SECRET).update(raw).digest('hex')
if (req.headers.get('x-maritime-signature') !== expected) {
return new Response('bad signature', { status: 401 })
}
const event = JSON.parse(raw)
// { event: 'agent.error', agent_id, external_id, timestamp, data: {...} }
console.log(event.event, 'for your customer', event.external_id)
return new Response('ok')
}Deliveries are best-effort and carry
X-Maritime-Event and X-Maritime-Delivery headers. An endpoint that fails repeatedly is auto-disabled; re-enable it (or update its events) via maritime.webhooks.list() and the dashboard.Runnable receivers
Full webhook receivers (Express + Flask) that verify the signature are in the examples.