{
  "openapi": "3.0.1",
  "info": {
    "title": "Webhooks API",
    "description": "Webhooks API",
    "version": "1.0"
  },
  "servers": [
    {
      "url": "https://api.bigchange.com"
    }
  ],
  "paths": {
    "/webhooks/v1/failed": {
      "get": {
        "tags": [
          "FailedMessages"
        ],
        "summary": "Get a list of failed messages",
        "description": "Retrieve a paged collection of failed webhook messages (required scope webhooks:read)",
        "parameters": [
          {
            "name": "appId",
            "in": "query",
            "description": "Only return messages where `app_id` matches the value(s) provided",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          {
            "name": "subId",
            "in": "query",
            "description": "Only return messages where `sub_id` matches the value(s) provided",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          {
            "name": "appName",
            "in": "query",
            "description": "Only return messages where `app_name` matches the value provided (case-insensitive)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "eventType",
            "in": "query",
            "description": "Only return messages where `event_type` matches the value provided (case-insensitive)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "httpStatus",
            "in": "query",
            "description": "Only return messages where the last retry error code matches the value provided",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lastAttemptFrom",
            "in": "query",
            "description": "Only return messages where the most recent `last_retried_at` is on or after this date (UTC)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "lastAttemptTo",
            "in": "query",
            "description": "Only return messages where the most recent `last_retried_at` is on or before this date (UTC)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "includeDeleted",
            "in": "query",
            "description": "When `true`, soft-deleted messages are included in the results",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "custId",
            "in": "query",
            "description": "Only return messages for the specified customer identifier",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only return messages with the specified status(es)",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/FailedMessageStatus"
              }
            }
          },
          {
            "name": "pageNumber",
            "in": "query",
            "description": "The page number being requested (minimum: 1, maximum: 1073741)",
            "schema": {
              "maximum": 1073741,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "The page size being requested (minimum: 1, maximum: 2000)",
            "schema": {
              "maximum": 2000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sortBy",
            "in": "query",
            "description": "The field to sort items in the page by",
            "schema": {
              "$ref": "#/components/schemas/FailedMessageSortOptions"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "description": "The direction to apply the sort",
            "schema": {
              "$ref": "#/components/schemas/SortDirection"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadFailedMessageModelPagedResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "FailedMessages"
        ],
        "summary": "Soft-delete a batch of failed messages",
        "description": "Soft-delete a batch of failed messages. All messages must exist, be in 'Failed' state, not already be deleted, and not have exhausted the maximum retry count (required scope webhooks:write)",
        "requestBody": {
          "description": "List of failed message IDs to delete (max 30)",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteFailedMessagesModel"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/v1/failed/retry": {
      "post": {
        "tags": [
          "FailedMessages"
        ],
        "summary": "Retry a batch of failed messages",
        "description": "Re-queue up to 30 failed messages for re-delivery. All messages must exist, be in 'Failed' state, not be deleted, and not have exhausted the maximum retry count (required scope webhooks:write)",
        "requestBody": {
          "description": "List of failed message IDs to retry (max 30)",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RetryFailedMessagesModel"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/v1/subscriptions": {
      "get": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "Get a list of subscriptions",
        "description": "Retrieve a paged collection of subscriptions (required scope webhooks:read)",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "description": "Only return subscriptions where `id` matches the value(s) provided",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          {
            "name": "applicationId",
            "in": "query",
            "description": "Only return subscriptions where `applicationId` matches the value(s) provided",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          {
            "name": "integratorId",
            "in": "query",
            "description": "Only return subscriptions where `integratorId` matches the value provided",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "pageNumber",
            "in": "query",
            "description": "The page number being requested (minimum: 1, maximum: 1073741)",
            "schema": {
              "maximum": 1073741,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "The page size being requested (minimum: 1, maximum: 2000)",
            "schema": {
              "maximum": 2000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sortBy",
            "in": "query",
            "description": "The field to sort items in the page by",
            "schema": {
              "$ref": "#/components/schemas/SubscriptionSortOptions"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "description": "The direction to apply the sort",
            "schema": {
              "$ref": "#/components/schemas/SortDirection"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadSubscriptionModelPagedResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/v1/subscriptions/{subscriptionId}": {
      "get": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "Get a subscription",
        "description": "Retrieve the details of a single subscription (required scope webhooks:read)",
        "parameters": [
          {
            "name": "subscriptionId",
            "in": "path",
            "description": "The unique identifier of the subscription",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadSubscriptionModel"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "DeleteFailedMessagesModel": {
        "required": [
          "ids"
        ],
        "type": "object",
        "properties": {
          "ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The identifiers of the failed messages to soft-delete"
          }
        },
        "additionalProperties": false,
        "description": "Request body for DELETE /v1/failed"
      },
      "FailedMessageSortOptions": {
        "enum": [
          "createdAt",
          "status",
          "eventType"
        ],
        "type": "string",
        "description": "Shows the possible values for sorting failed messages",
        "example": "createdAt"
      },
      "FailedMessageStatus": {
        "enum": [
          "failed",
          "permanentlyFailed",
          "resent"
        ],
        "type": "string",
        "example": "failed"
      },
      "ProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "A URI reference [RFC3986] that identifies the problem type",
            "nullable": true,
            "example": "https://example.com/probs/out-of-credit"
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type",
            "nullable": true,
            "example": "You do not have enough credit"
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code([RFC7231], Section 6) generated by the origin server for this occurrence of the problem",
            "format": "int32",
            "nullable": true,
            "example": 403
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence of the problem",
            "nullable": true,
            "example": "Your current balance is 30, but that costs 50"
          },
          "instance": {
            "type": "string",
            "description": "A URI reference that identifies the specific occurrence of the problem",
            "nullable": true,
            "example": "/account/12345/msgs/abc"
          }
        },
        "additionalProperties": { }
      },
      "ReadEventTypeModel": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The name of the event type",
            "example": "job.modified"
          },
          "requiredScope": {
            "type": "string",
            "description": "The required scope for the event type",
            "example": "requiredScope"
          }
        },
        "additionalProperties": false,
        "description": "Represents a data transfer object for reading event type details"
      },
      "ReadFailedMessageHistoryModel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the history record",
            "format": "uuid",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          },
          "errorMessage": {
            "type": "string",
            "description": "The error message returned by the endpoint",
            "example": "Connection timed out"
          },
          "errorCode": {
            "type": "string",
            "description": "The HTTP status code or error code returned",
            "example": "503"
          },
          "lastRetriedAt": {
            "type": "string",
            "description": "The date and time of the last retry attempt (UTC)",
            "format": "date-time",
            "example": "2026-01-15T10:30:00.0000000+00:00"
          }
        },
        "additionalProperties": false,
        "description": "Represents a single retry attempt for a failed message"
      },
      "ReadFailedMessageModel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the failed message",
            "format": "uuid",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          },
          "sqsMessageId": {
            "type": "string",
            "description": "The SQS message identifier",
            "example": "abc123def456"
          },
          "custId": {
            "type": "integer",
            "description": "The customer identifier",
            "format": "int64",
            "example": 457
          },
          "integratorId": {
            "type": "string",
            "description": "The integrator identifier",
            "format": "uuid",
            "example": "8a794625-8ed8-4931-927d-bd9a41e44713"
          },
          "appId": {
            "type": "string",
            "description": "The application identifier",
            "format": "uuid",
            "example": "0196c9f3-d2b2-77de-9a42-0fd45a4fe44e"
          },
          "appName": {
            "type": "string",
            "description": "The application name",
            "example": "MyIntegration"
          },
          "subId": {
            "type": "string",
            "description": "The subscription identifier",
            "format": "uuid",
            "example": "7d3a2b1c-4e5f-6789-abcd-ef0123456789"
          },
          "status": {
            "$ref": "#/components/schemas/FailedMessageStatus"
          },
          "eventType": {
            "type": "string",
            "description": "The event type of the original message",
            "example": "job.created"
          },
          "sendUrl": {
            "type": "string",
            "description": "The URL the webhook was sent to",
            "example": "https://example.com/webhooks"
          },
          "messageBody": {
            "type": "string",
            "description": "The original webhook payload"
          },
          "createdAt": {
            "type": "string",
            "description": "The date and time of the first delivery attempt (UTC)",
            "format": "date-time",
            "example": "2026-01-15T10:00:00.0000000+00:00"
          },
          "deletedAt": {
            "type": "string",
            "description": "The date and time the message was soft-deleted, if applicable",
            "format": "date-time",
            "nullable": true,
            "example": "2026-01-16T08:00:00.0000000+00:00"
          },
          "history": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReadFailedMessageHistoryModel"
            },
            "description": "The history of retry attempts for this message"
          }
        },
        "additionalProperties": false,
        "description": "Represents a failed webhook message"
      },
      "ReadFailedMessageModelPagedResponse": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReadFailedMessageModel"
            },
            "description": "The items returned for the requested page"
          },
          "pageNumber": {
            "type": "integer",
            "description": "The page number of the response where 1 is the first page",
            "format": "int32",
            "example": 2
          },
          "pageSize": {
            "type": "integer",
            "description": "The number of items requested for the current page",
            "format": "int32",
            "example": 100
          },
          "pageItemCount": {
            "type": "integer",
            "description": "The number of items returned in the current page",
            "format": "int32",
            "readOnly": true,
            "example": 55
          }
        },
        "additionalProperties": false,
        "description": "A paged collection of items"
      },
      "ReadSubscriptionModel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the subscription",
            "format": "uuid",
            "example": "0196c9f3-d2b2-77de-9a42-0fd45a4fe44e"
          },
          "description": {
            "type": "string",
            "description": "A brief description of the subscription",
            "example": "Example description"
          },
          "url": {
            "type": "string",
            "description": "The url to send the webhook events to",
            "example": "https://example.com"
          },
          "isActive": {
            "type": "boolean",
            "description": "Determines if the subscription should send webhook events",
            "example": true
          },
          "createdAt": {
            "type": "string",
            "description": "The date and time when the subscription was created",
            "format": "date-time",
            "example": "2025-05-13T14:02:01.0000000+00:00"
          },
          "integratorId": {
            "type": "string",
            "description": "The id of the integrator (organisation) that owns the subscription",
            "format": "uuid",
            "example": "1c3c1624-8f42-41a6-a150-ed2ea9986de6"
          },
          "applicationId": {
            "type": "string",
            "description": "The id of the application that owns the subscription",
            "format": "uuid",
            "example": "8a794625-8ed8-4931-927d-bd9a41e44713"
          },
          "modifiedAt": {
            "type": "string",
            "description": "The date and time when the subscription was modified",
            "format": "date-time",
            "example": "2025-05-13T14:02:01.0000000+00:00"
          },
          "eventTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReadEventTypeModel"
            },
            "description": "The webhook events the subscription will listen for"
          }
        },
        "additionalProperties": false,
        "description": "Represents a data transfer object for reading subscription details"
      },
      "ReadSubscriptionModelPagedResponse": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReadSubscriptionModel"
            },
            "description": "The items returned for the requested page"
          },
          "pageNumber": {
            "type": "integer",
            "description": "The page number of the response where 1 is the first page",
            "format": "int32",
            "example": 2
          },
          "pageSize": {
            "type": "integer",
            "description": "The number of items requested for the current page",
            "format": "int32",
            "example": 100
          },
          "pageItemCount": {
            "type": "integer",
            "description": "The number of items returned in the current page",
            "format": "int32",
            "readOnly": true,
            "example": 55
          }
        },
        "additionalProperties": false,
        "description": "A paged collection of items"
      },
      "RetryFailedMessagesModel": {
        "required": [
          "ids"
        ],
        "type": "object",
        "properties": {
          "ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The identifiers of the failed messages to retry. Maximum of 30"
          }
        },
        "additionalProperties": false,
        "description": "Request body for POST /v1/failed/retry"
      },
      "SortDirection": {
        "enum": [
          "ascending",
          "descending"
        ],
        "type": "string",
        "description": "Represents the direction in which sorting should be applied",
        "example": "ascending"
      },
      "SubscriptionSortOptions": {
        "enum": [
          "createdAt"
        ],
        "type": "string",
        "description": "Shows the possible values for sorting",
        "example": "createdAt"
      },
      "ValidationProblemDetails": {
        "type": "object",
        "properties": {
          "errors": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "type": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "detail": {
            "type": "string",
            "nullable": true
          },
          "instance": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": { }
      }
    },
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "description": "Enter the access token only.",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  },
  "security": [
    {
      "bearer": [ ]
    }
  ]
}