{
    "asyncapi": "3.0.0",
    "info": {
        "title": "Stepes Public API Webhooks",
        "version": "2.0.0",
        "description": "Signed notifications for quote, project, and delivery changes. Events may be retried, so webhook handlers must deduplicate them by event id."
    },
    "servers": {
        "customerEndpoint": {
            "host": "customer.example",
            "protocol": "https",
            "description": "The HTTPS endpoint registered through POST /v2/webhooks."
        }
    },
    "channels": {
        "clientWebhook": {
            "address": "/registered-webhook-path",
            "description": "Customer-owned callback URL. Redirects and private network targets are rejected.",
            "messages": {
                "quoteCreated": {
                    "$ref": "#/components/messages/QuoteCreated"
                },
                "quoteUpdated": {
                    "$ref": "#/components/messages/QuoteUpdated"
                },
                "quoteSubmitted": {
                    "$ref": "#/components/messages/QuoteSubmitted"
                },
                "quoteAccepted": {
                    "$ref": "#/components/messages/QuoteAccepted"
                },
                "projectCreated": {
                    "$ref": "#/components/messages/ProjectCreated"
                },
                "projectUpdated": {
                    "$ref": "#/components/messages/ProjectUpdated"
                },
                "projectCancelled": {
                    "$ref": "#/components/messages/ProjectCancelled"
                },
                "projectCompleted": {
                    "$ref": "#/components/messages/ProjectCompleted"
                },
                "deliveryReady": {
                    "$ref": "#/components/messages/DeliveryReady"
                }
            }
        }
    },
    "operations": {
        "deliverLifecycleEvent": {
            "action": "send",
            "summary": "Deliver a persisted Stepes lifecycle event",
            "channel": {
                "$ref": "#/channels/clientWebhook"
            },
            "messages": [
                {
                    "$ref": "#/channels/clientWebhook/messages/quoteCreated"
                },
                {
                    "$ref": "#/channels/clientWebhook/messages/quoteUpdated"
                },
                {
                    "$ref": "#/channels/clientWebhook/messages/quoteSubmitted"
                },
                {
                    "$ref": "#/channels/clientWebhook/messages/quoteAccepted"
                },
                {
                    "$ref": "#/channels/clientWebhook/messages/projectCreated"
                },
                {
                    "$ref": "#/channels/clientWebhook/messages/projectUpdated"
                },
                {
                    "$ref": "#/channels/clientWebhook/messages/projectCancelled"
                },
                {
                    "$ref": "#/channels/clientWebhook/messages/projectCompleted"
                },
                {
                    "$ref": "#/channels/clientWebhook/messages/deliveryReady"
                }
            ]
        }
    },
    "components": {
        "messages": {
            "QuoteCreated": {
                "name": "quote.created",
                "title": "Quote created",
                "summary": "A quote was created.",
                "x-stepes-category": "Quotes",
                "x-stepes-trigger": "A new quote became available after quote or project creation.",
                "x-stepes-source-operations": [
                    "createQuote",
                    "createProject"
                ],
                "x-stepes-schema-version": "1.0",
                "contentType": "application/json",
                "headers": {
                    "$ref": "#/components/schemas/WebhookHeaders"
                },
                "payload": {
                    "allOf": [
                        {
                            "$ref": "#/components/schemas/EventEnvelope"
                        },
                        {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "const": "quote.created"
                                }
                            }
                        }
                    ]
                }
            },
            "QuoteUpdated": {
                "name": "quote.updated",
                "title": "Quote updated",
                "summary": "Quote inputs, pricing, or lifecycle state changed.",
                "x-stepes-category": "Quotes",
                "x-stepes-trigger": "Quote details, pricing, or status changed.",
                "x-stepes-source-operations": [
                    "updateQuote"
                ],
                "x-stepes-schema-version": "1.0",
                "contentType": "application/json",
                "headers": {
                    "$ref": "#/components/schemas/WebhookHeaders"
                },
                "payload": {
                    "allOf": [
                        {
                            "$ref": "#/components/schemas/EventEnvelope"
                        },
                        {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "const": "quote.updated"
                                }
                            }
                        }
                    ]
                }
            },
            "QuoteSubmitted": {
                "name": "quote.submitted",
                "title": "Quote submitted",
                "summary": "A quote was submitted and can no longer be edited.",
                "x-stepes-category": "Quotes",
                "x-stepes-trigger": "POST /v2/quotes/{quoteId}/submit completed.",
                "x-stepes-source-operations": [
                    "submitQuote"
                ],
                "x-stepes-schema-version": "1.0",
                "contentType": "application/json",
                "headers": {
                    "$ref": "#/components/schemas/WebhookHeaders"
                },
                "payload": {
                    "allOf": [
                        {
                            "$ref": "#/components/schemas/EventEnvelope"
                        },
                        {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "const": "quote.submitted"
                                }
                            }
                        }
                    ]
                }
            },
            "QuoteAccepted": {
                "name": "quote.accepted",
                "title": "Quote accepted",
                "summary": "A quote was accepted and project creation started.",
                "x-stepes-category": "Quotes",
                "x-stepes-trigger": "Quote acceptance completed and a translation project was created.",
                "x-stepes-source-operations": [
                    "acceptQuote",
                    "createProject"
                ],
                "x-stepes-schema-version": "1.0",
                "contentType": "application/json",
                "headers": {
                    "$ref": "#/components/schemas/WebhookHeaders"
                },
                "payload": {
                    "allOf": [
                        {
                            "$ref": "#/components/schemas/EventEnvelope"
                        },
                        {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "const": "quote.accepted"
                                }
                            }
                        }
                    ]
                }
            },
            "ProjectCreated": {
                "name": "project.created",
                "title": "Project created",
                "summary": "A translation project was created.",
                "x-stepes-category": "Projects",
                "x-stepes-trigger": "POST /v2/projects or quote acceptance created a project.",
                "x-stepes-source-operations": [
                    "createProject",
                    "acceptQuote"
                ],
                "x-stepes-schema-version": "1.0",
                "contentType": "application/json",
                "headers": {
                    "$ref": "#/components/schemas/WebhookHeaders"
                },
                "payload": {
                    "allOf": [
                        {
                            "$ref": "#/components/schemas/EventEnvelope"
                        },
                        {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "const": "project.created"
                                }
                            }
                        }
                    ]
                }
            },
            "ProjectUpdated": {
                "name": "project.updated",
                "title": "Project updated",
                "summary": "Project status, progress, or delivery availability changed.",
                "x-stepes-category": "Projects",
                "x-stepes-trigger": "The project's status, progress, or available results changed.",
                "x-stepes-source-operations": [],
                "x-stepes-schema-version": "1.0",
                "contentType": "application/json",
                "headers": {
                    "$ref": "#/components/schemas/WebhookHeaders"
                },
                "payload": {
                    "allOf": [
                        {
                            "$ref": "#/components/schemas/EventEnvelope"
                        },
                        {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "const": "project.updated"
                                }
                            }
                        }
                    ]
                }
            },
            "ProjectCancelled": {
                "name": "project.cancelled",
                "title": "Project cancelled",
                "summary": "A project was cancelled.",
                "x-stepes-category": "Projects",
                "x-stepes-trigger": "A project reached the cancelled state.",
                "x-stepes-source-operations": [
                    "cancelProject"
                ],
                "x-stepes-schema-version": "1.0",
                "contentType": "application/json",
                "headers": {
                    "$ref": "#/components/schemas/WebhookHeaders"
                },
                "payload": {
                    "allOf": [
                        {
                            "$ref": "#/components/schemas/EventEnvelope"
                        },
                        {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "const": "project.cancelled"
                                }
                            }
                        }
                    ]
                }
            },
            "ProjectCompleted": {
                "name": "project.completed",
                "title": "Project completed",
                "summary": "All requested translations are complete.",
                "x-stepes-category": "Projects",
                "x-stepes-trigger": "The project reached the completed state.",
                "x-stepes-source-operations": [],
                "x-stepes-schema-version": "1.0",
                "contentType": "application/json",
                "headers": {
                    "$ref": "#/components/schemas/WebhookHeaders"
                },
                "payload": {
                    "allOf": [
                        {
                            "$ref": "#/components/schemas/EventEnvelope"
                        },
                        {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "const": "project.completed"
                                }
                            }
                        }
                    ]
                }
            },
            "DeliveryReady": {
                "name": "delivery.ready",
                "title": "Delivery ready",
                "summary": "A translated file or structured result is ready.",
                "x-stepes-category": "Deliveries",
                "x-stepes-trigger": "A new project delivery became available for download or retrieval.",
                "x-stepes-source-operations": [],
                "x-stepes-schema-version": "1.0",
                "contentType": "application/json",
                "headers": {
                    "$ref": "#/components/schemas/WebhookHeaders"
                },
                "payload": {
                    "allOf": [
                        {
                            "$ref": "#/components/schemas/EventEnvelope"
                        },
                        {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "const": "delivery.ready"
                                }
                            }
                        }
                    ]
                }
            }
        },
        "schemas": {
            "WebhookHeaders": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                    "Stepes-Webhook-Id",
                    "Stepes-Webhook-Delivery-Id",
                    "Stepes-Webhook-Timestamp",
                    "Stepes-Webhook-Signature"
                ],
                "properties": {
                    "Stepes-Webhook-Id": {
                        "type": "string",
                        "pattern": "^evt_",
                        "description": "Stable event identifier used for consumer deduplication."
                    },
                    "Stepes-Webhook-Delivery-Id": {
                        "type": "string",
                        "pattern": "^whd_",
                        "description": "Stable delivery identifier for this endpoint and event."
                    },
                    "Stepes-Webhook-Timestamp": {
                        "type": "string",
                        "pattern": "^[0-9]+$",
                        "description": "Unix timestamp included in the signed material."
                    },
                    "Stepes-Webhook-Signature": {
                        "type": "string",
                        "pattern": "^v1=[a-f0-9]{64}(,v1=[a-f0-9]{64})?$"
                    }
                }
            },
            "EventType": {
                "type": "string",
                "enum": [
                    "quote.created",
                    "quote.updated",
                    "quote.submitted",
                    "quote.accepted",
                    "project.created",
                    "project.updated",
                    "project.cancelled",
                    "project.completed",
                    "delivery.ready"
                ]
            },
            "EventEnvelope": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                    "id",
                    "object",
                    "type",
                    "created_at",
                    "data"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "pattern": "^evt_",
                        "description": "Stable event ID used for consumer deduplication."
                    },
                    "object": {
                        "const": "event"
                    },
                    "type": {
                        "$ref": "#/components/schemas/EventType"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "data": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                            "object"
                        ],
                        "properties": {
                            "object": {
                                "type": "object",
                                "additionalProperties": true,
                                "description": "Quote, project, or delivery data using public API fields and IDs."
                            }
                        }
                    }
                }
            }
        }
    }
}
