{
  "openapi": "3.1.0",
  "info": {
    "title": "Arknox Webhooks",
    "version": "1.0.0",
    "description": "Arknox delivers real-time event notifications to webhook URLs you configure in your dashboard (Settings → Webhooks). This spec documents the outbound payloads Arknox sends to your endpoint — there is no inbound REST API to call. Every event shares the same envelope and signature scheme; only the `data` object differs per event.",
    "contact": { "name": "Arknox Support", "email": "support@arknox.in", "url": "https://youtube-embedder.arknox.in/support" }
  },
  "externalDocs": {
    "description": "Full webhook guide with verification code samples",
    "url": "https://youtube-embedder.arknox.in/developers"
  },
  "webhooks": {
    "form.submitted": {
      "post": {
        "summary": "Lead capture or gate form submitted",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WebhookEnvelope" },
              "examples": {
                "form.submitted": {
                  "value": {
                    "event": "form.submitted",
                    "timestamp": "2026-08-23T09:00:00.000Z",
                    "data": {
                      "submissionId": "clv2x...",
                      "videoId": "clv1a...",
                      "videoTitle": "Product Demo",
                      "overlayId": "clv3b...",
                      "sessionId": "sess_...",
                      "viewerIdentifier": null,
                      "responses": { "name": "Jane Doe", "email": "jane@example.com" }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "Any 2xx response is treated as delivered. Arknox does not retry failed deliveries." } }
      }
    },
    "quiz.submitted": {
      "post": {
        "summary": "Multiple-choice quiz question answered",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WebhookEnvelope" },
              "examples": {
                "quiz.submitted": {
                  "value": {
                    "event": "quiz.submitted",
                    "timestamp": "2026-08-23T09:00:00.000Z",
                    "data": {
                      "responseId": "clv4c...",
                      "videoId": "clv1a...",
                      "videoTitle": "Product Demo",
                      "questionId": "clv5d...",
                      "questionText": "What feature do you use most?",
                      "sessionId": "sess_...",
                      "viewerIdentifier": null,
                      "answerGiven": "Interactive overlays"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "Any 2xx response is treated as delivered." } }
      }
    },
    "poll.submitted": {
      "post": {
        "summary": "Poll answered",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WebhookEnvelope" },
              "examples": {
                "poll.submitted": {
                  "value": {
                    "event": "poll.submitted",
                    "timestamp": "2026-08-23T09:00:00.000Z",
                    "data": {
                      "responseId": "clv6e...",
                      "overlayId": "clv3b...",
                      "videoId": "clv1a...",
                      "videoTitle": "Product Demo",
                      "sessionId": "sess_...",
                      "viewerIdentifier": null,
                      "answerGiven": "Option A"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "Any 2xx response is treated as delivered." } }
      }
    },
    "booking.submitted": {
      "post": {
        "summary": "Booking widget submitted",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WebhookEnvelope" },
              "examples": {
                "booking.submitted": {
                  "value": {
                    "event": "booking.submitted",
                    "timestamp": "2026-08-23T09:00:00.000Z",
                    "data": {
                      "submissionId": "clv7f...",
                      "overlayId": "clv3b...",
                      "videoId": "clv1a...",
                      "videoTitle": "Product Demo",
                      "sessionId": "sess_...",
                      "viewerIdentifier": null,
                      "bookingType": "call",
                      "responses": { "name": "Jane Doe", "email": "jane@example.com", "preferredTime": "2026-08-25T14:00:00.000Z" }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "Any 2xx response is treated as delivered." } }
      }
    },
    "note.created": {
      "post": {
        "summary": "Timestamped viewer note created",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WebhookEnvelope" },
              "examples": {
                "note.created": {
                  "value": {
                    "event": "note.created",
                    "timestamp": "2026-08-23T09:00:00.000Z",
                    "data": {
                      "videoId": "clv1a...",
                      "videoTitle": "Product Demo",
                      "sessionId": "sess_...",
                      "timestamp": 128,
                      "noteId": "clv8g..."
                    }
                  }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "Any 2xx response is treated as delivered." } }
      }
    },
    "video.duplicated": {
      "post": {
        "summary": "Video duplicated in the dashboard",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WebhookEnvelope" },
              "examples": {
                "video.duplicated": {
                  "value": {
                    "event": "video.duplicated",
                    "timestamp": "2026-08-23T09:00:00.000Z",
                    "data": {
                      "sourceVideoId": "clv1a...",
                      "newVideoId": "clv9h...",
                      "userId": "clvai...",
                      "title": "Product Demo (Copy)",
                      "sourceTitle": "Product Demo"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "Any 2xx response is treated as delivered." } }
      }
    },
    "video.expired": {
      "post": {
        "summary": "Embed link reached its expiry date",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WebhookEnvelope" },
              "examples": {
                "video.expired": {
                  "value": {
                    "event": "video.expired",
                    "timestamp": "2026-08-23T09:00:00.000Z",
                    "data": {
                      "videoId": "clv1a...",
                      "userId": "clvai...",
                      "token": "d5e12f4174201f9c2b7e41599df196c4",
                      "expiresAt": "2026-08-23T00:00:00.000Z"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "Any 2xx response is treated as delivered." } }
      }
    }
  },
  "components": {
    "schemas": {
      "WebhookEnvelope": {
        "type": "object",
        "required": ["event", "timestamp", "data"],
        "properties": {
          "event": {
            "type": "string",
            "enum": ["form.submitted", "quiz.submitted", "poll.submitted", "booking.submitted", "note.created", "video.duplicated", "video.expired"]
          },
          "timestamp": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp of when the event fired." },
          "data": { "type": "object", "description": "Event-specific payload — see the example for each event above." }
        }
      }
    },
    "securitySchemes": {
      "webhookSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Webhook-Signature",
        "description": "Present only if a secret is configured for the webhook. Value is `sha256=<hex>`, an HMAC-SHA256 of the exact raw JSON request body using your webhook secret as the key. Recompute and compare with a constant-time check before trusting the payload. The event name is also sent unsigned in the `X-Webhook-Event` header for routing."
      }
    }
  }
}
