Skip to content

Webhook Reference

Not yet available. Webhook delivery is on the roadmap but not currently active. Use polling (Step 4 / SR20) to check policy status in production integrations. This page documents the planned interface so you can design your integration for it in advance.

Webhooks will let you receive real-time notifications when a policy status changes, instead of polling Step 4 repeatedly.


Setting Up a Webhook

Include a webHook field in addtnlFact when submitting a policy request (Step 3):

{
  "cmmnd": {
    "cmmnd": "entt_{CONSUMER_ID}: insure",
    "seed": {
      "ctgry": "vhcl",
      "type": "tprt",
      "pckg": "1111",
      "id": "YOUR_TRANSACTION_REF",
      "addtnlFact": {
        "brand": "Toyota",
        "model": "Camry",
        "year": "2019",
        "chsssId": "JTDBE32KX30123456",
        "engineId": "2AR1234567",
        "rgstrtId": "LSR-123AB",
        "webHook": "https://yourplatform.com/webhooks/octamile"
      }
    }
  }
}

Your webhook URL must be publicly reachable over HTTPS. Octamile will send a POST request to this URL when the policy status changes.


Webhook Payload

When the policy status changes to approved ("a") or declined ("d"), Octamile sends a POST request to your webhook URL with this JSON body:

{
  "product": "vhcl-tprt-1111",
  "consumerId": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
  "trnsctnId": "z9y8x7w6v5u4z9y8x7w6v5u4z9y8x7w6",
  "status": "a",
  "statusNote": "",
  "crtfct": "/9j/4AAQSkZJRgABAQAA...",
  "crtfctType": "jpg"
}

Payload Fields

Field Type Description
product string Product code (e.g., vhcl-tprt-1111)
consumerId string The consumer's 32-character ID
trnsctnId string Your transaction reference from Step 3
status string "a" (approved) or "d" (declined)
statusNote string Reason for decline — empty if approved
crtfct string Base64-encoded certificate — present only if approved
crtfctType string Certificate format: "jpg", "png", or "pdf"

Handling the Webhook

Your endpoint must:

  1. Return HTTP 200 promptly (within 5 seconds). Do any heavy processing asynchronously.
  2. Verify the trnsctnId matches a transaction you initiated.
  3. Check status and act accordingly:
  4. "a" — Activate the policy in your system, decode and store the certificate, notify the consumer.
  5. "d" — Refund the consumer, log the statusNote for support.

Example handler (Node.js / Express):

app.post('/webhooks/octamile', express.json(), (req, res) => {
  // Respond immediately
  res.sendStatus(200);

  const { product, consumerId, trnsctnId, status, statusNote, crtfct, crtfctType } = req.body;

  // Verify this transaction belongs to your system
  const transaction = db.findTransaction(trnsctnId);
  if (!transaction) {
    console.error(`Unknown transaction: ${trnsctnId}`);
    return;
  }

  if (status === 'a') {
    // Decode and store certificate
    const certBuffer = Buffer.from(crtfct, 'base64');
    storage.save(`${trnsctnId}.${crtfctType}`, certBuffer);

    // Activate policy and notify consumer
    db.activatePolicy(trnsctnId);
    notifications.sendCertificate(transaction.consumerEmail, certBuffer, crtfctType);

  } else if (status === 'd') {
    // Mark declined and refund
    db.declinePolicy(trnsctnId, statusNote);
    payments.refund(transaction.paymentRef);
    notifications.sendDeclineNotice(transaction.consumerEmail, statusNote);
  }
});

Example handler (Python / Flask):

from flask import Flask, request
import base64

app = Flask(__name__)

@app.route('/webhooks/octamile', methods=['POST'])
def octamile_webhook():
    data = request.json

    # Respond immediately
    response = ('', 200)

    trn_id = data['trnsctnId']
    status = data['status']

    transaction = db.find_transaction(trn_id)
    if not transaction:
        return response

    if status == 'a':
        cert_data = base64.b64decode(data['crtfct'])
        cert_path = f"certificates/{trn_id}.{data['crtfctType']}"
        with open(cert_path, 'wb') as f:
            f.write(cert_data)
        db.activate_policy(trn_id)

    elif status == 'd':
        db.decline_policy(trn_id, data.get('statusNote'))

    return response

Webhooks vs. Polling

Webhook Polling (Step 4)
Recommended for Production integrations Testing and debugging
Latency Instant Depends on poll interval
Server load Low Higher
Requires public URL Yes No
Handles all status changes Yes Only when you poll

Use webhooks in production. Use polling during development when you don't have a public URL — tools like ngrok can expose a local server for webhook testing.


Webhook Not Received?

If your webhook is not being called:

  1. Confirm the URL is publicly reachable over HTTPS — test it with a tool like curl or Postman.
  2. Check that your URL was included in the addtnlFact.webHook field of your Step 3 request.
  3. Poll Step 4 to confirm the policy status has actually changed. Webhooks only fire on status changes.
  4. Check your server logs for incoming requests on the webhook path — the notification may have arrived but your handler errored.

If the policy is approved but no webhook arrived and polling confirms it, contact Octamile support with your trnsctnId.