swagger: "2.0" info: description: "An API which facilitates the creation, modification, and deletion of bundles. A bundle is a collection of datasets which are to be published at the same date and time." version: "1.0.0" title: "Bundle Administration" license: name: "Open Government Licence v3.0" url: "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/" basePath: "/v1" tags: - name: "Private" description: "Endpoints that are not available to the public" schemes: - "http" security: - Authorization: [] parameters: after_filter: name: after type: string format: date-time description: "The date from which to query bundle events" in: query required: false before_filter: name: before type: string format: date-time description: "The date to which to query bundle events" in: query required: false bundle: required: true name: bundle schema: $ref: "#/definitions/Bundle" description: "The bundle definition" in: body bundle_id: name: id type: string required: true description: "The unique bundle ID for grouping datasets" in: path bundle_id_filter: name: bundle description: "The bundle ID to filter the bundle to return events for." in: query required: false type: string pattern: "^[a-z0-9]+(-[a-z0-9]+)*$" content_item: required: true name: content schema: $ref: "#/definitions/ContentItem" description: "The content definition" in: body content_id: name: content_id type: string required: true description: "The unique content ID for an item in a bundle" in: path if_match: description: | The RFC9110 `If-Match` header requires the provided entity-tag (`ETag` header value from the previous read request) to match the resources current entity-tag. This prevents the changes from being applied if there have been any changes to the resource since the client last read the resource. If the header value does not match a `409 Conflict` error will be returned. name: If-Match in: header required: true type: string pattern: ^(?:W/)?"(?:[!#-~])+"$ limit: name: limit description: "Maximum number of items that will be returned. A value of zero will return zero items." in: query required: false type: integer default: 20 minimum: 0 maximum: 1000 offset: name: offset description: "Starting index of the items array that will be returned. By default it is zero, meaning that the returned items will start from the beginning." in: query required: false type: integer default: 0 minimum: 0 publish_date: name: publish_date description: "Filter bundles by their scheduled publication date. Accepts an optional datetime value and returns all bundles where the scheduled_at field matches the specified datetime." in: query required: false type: string format: date-time bundle_state: required: true name: bundle_state schema: $ref: "#/definitions/BundleState" description: "The state definition of the bundle as a whole." in: body update_bundle: required: true name: update_bundle schema: $ref: "#/definitions/Bundle" description: "The fields to update in the bundle" in: body securityDefinitions: Authorization: name: Authorization description: "Access token provided by Auth Service in a Bearer format. Can be a human or service user token." in: header type: apiKey paths: /bundles: get: tags: - "Private" summary: "List bundles" description: "Returns a list of all bundles available." parameters: - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" - $ref: "#/parameters/publish_date" produces: - "application/json" responses: 200: description: "A json list containing bundles" headers: ETag: description: The RFC9110 ETag header field. Defines the unique entity tag for the current state of the resource. This is used for setting the `If-Match` and `If-None-Match` headers on subsequent requests. type: string pattern: ^(?:W/)?"(?:[!#-~])+"$ Cache-Control: description: The RFC9111 Cache-Control header field for the response which instructs how to handle caching the resource. type: string schema: $ref: "#/definitions/Bundles" 400: $ref: "#/responses/InvalidRequest" 401: $ref: "#/responses/UnauthorisedError" 403: $ref: "#/responses/ForbiddenError" 500: $ref: "#/responses/InternalError" post: tags: - "Private" summary: "Create a bundle" description: "Creates a bundle in the database which groups datasets together to be published on the same date and time" consumes: - "application/json" produces: - "application/json" parameters: - $ref: "#/parameters/bundle" responses: 201: description: "bundle was created" headers: ETag: description: The RFC9110 ETag header field. Defines the unique entity tag for the current state of the resource. This is used for setting the `If-Match` and `If-None-Match` headers on subsequent requests. type: string pattern: ^(?:W/)?"(?:[!#-~])+"$ Cache-Control: description: The RFC9111 Cache-Control header field for the response which instructs how to handle caching the resource. type: string Location: description: The RFC9110 Location header field. Defines the access location (i.e. path) of the primary resource created for use in subsequent requests. type: string schema: $ref: "#/definitions/Bundle" 400: $ref: "#/responses/InvalidRequest" 401: $ref: "#/responses/UnauthorisedError" 403: $ref: "#/responses/ForbiddenError" 409: $ref: "#/responses/Conflict" 500: $ref: "#/responses/InternalError" /bundles/{id}: parameters: - $ref: "#/parameters/bundle_id" get: tags: - "Private" summary: "Get a bundle" description: "Get information for a specific bundle" produces: - "application/json" responses: 200: description: "The bundle was found and document is returned" headers: ETag: description: The RFC9110 ETag header field. Defines the unique entity tag for the current state of the resource. This is used for setting the `If-Match` and `If-None-Match` headers on subsequent requests. type: string pattern: ^(?:W/)?"(?:[!#-~])+"$ Cache-Control: description: The RFC9111 Cache-Control header field for the response which instructs how to handle caching the resource. type: string schema: $ref: "#/definitions/Bundle" 404: $ref: "#/responses/NotFound" 401: $ref: "#/responses/UnauthorisedError" 403: $ref: "#/responses/ForbiddenError" 500: $ref: "#/responses/InternalError" put: tags: - "Private" summary: "Update a bundle" description: "Update the bundle by providing updated information." consumes: - "application/json" produces: - "application/json" parameters: - $ref: "#/parameters/if_match" - $ref: "#/parameters/update_bundle" responses: 200: description: "The bundle has been updated" headers: ETag: description: The RFC9110 ETag header field. Defines the unique entity tag for the current state of the resource. This is used for setting the `If-Match` and `If-None-Match` headers on subsequent requests. type: string pattern: ^(?:W/)?"(?:[!#-~])+"$ Cache-Control: description: The RFC9111 Cache-Control header field for the response which instructs how to handle caching the resource. type: string schema: $ref: "#/definitions/Bundle" 400: $ref: "#/responses/InvalidRequest" 401: $ref: "#/responses/UnauthorisedError" 403: $ref: "#/responses/ForbiddenError" 404: $ref: "#/responses/NotFound" 409: $ref: "#/responses/Conflict" 500: $ref: "#/responses/InternalError" delete: tags: - "Private" summary: "Delete a bundle" description: "Deletes a bundle and removes it from the scheduler if it's for a scheduled publication." parameters: - $ref: "#/parameters/bundle_id" responses: 204: description: "The bundle was removed" 401: $ref: "#/responses/UnauthorisedError" 403: $ref: "#/responses/ForbiddenError" 404: $ref: "#/responses/NotFound" 409: $ref: "#/responses/Conflict" 500: $ref: "#/responses/InternalError" /bundles/{id}/contents: parameters: - $ref: "#/parameters/bundle_id" get: parameters: - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" tags: - "Private" summary: "Get a list of contents within a bundle" description: "Get a list of contents within a bundle" produces: - "application/json" responses: 200: description: "The bundle was found and the list of contents is returned" headers: ETag: description: The RFC9110 ETag header field. Defines the unique entity tag for the current state of the resource. This is used for setting the `If-Match` and `If-None-Match` headers on subsequent requests. type: string pattern: ^(?:W/)?"(?:[!#-~])+"$ Cache-Control: description: The RFC9111 Cache-Control header field for the response which instructs how to handle caching the resource. type: string schema: $ref: "#/definitions/Contents" 400: $ref: "#/responses/InvalidRequest" 401: $ref: "#/responses/UnauthorisedError" 403: $ref: "#/responses/ForbiddenError" 404: $ref: "#/responses/NotFound" 500: $ref: "#/responses/InternalError" post: tags: - "Private" summary: "Add a dataset item to a bundle" description: "Adds the dataset item to the list of items to be published as part of the bundle" consumes: - "application/json" produces: - "application/json" parameters: - $ref: "#/parameters/content_item" responses: 201: description: "Content was added" headers: ETag: description: The RFC9110 ETag header field. Defines the unique entity tag for the current state of the resource. This is used for setting the `If-Match` and `If-None-Match` headers on subsequent requests. type: string pattern: ^(?:W/)?"(?:[!#-~])+"$ Cache-Control: description: The RFC9111 Cache-Control header field for the response which instructs how to handle caching the resource. type: string Location: description: The RFC9110 Location header field. Defines the access location (i.e. path) of the primary resource created for use in subsequent requests. type: string schema: $ref: "#/definitions/ContentItem" 400: $ref: "#/responses/InvalidRequest" 401: $ref: "#/responses/UnauthorisedError" 404: $ref: "#/responses/NotFound" 403: $ref: "#/responses/ForbiddenError" 409: $ref: "#/responses/Conflict" 500: $ref: "#/responses/InternalError" /bundles/{id}/contents/{content_id}: delete: tags: - "Private" summary: "Delete a content item from a bundle" description: "Deletes a content item from a bundle." parameters: - $ref: "#/parameters/bundle_id" - $ref: "#/parameters/content_id" responses: 204: description: "The content was removed" 401: $ref: "#/responses/UnauthorisedError" 403: $ref: "#/responses/ForbiddenError" 404: $ref: "#/responses/NotFound" 409: $ref: "#/responses/Conflict" 500: $ref: "#/responses/InternalError" /bundles/{id}/state: put: parameters: - $ref: "#/parameters/if_match" - $ref: "#/parameters/bundle_id" - $ref: "#/parameters/bundle_state" tags: - "Private" summary: "Updates the state of a bundle" description: "Updates the state of a bundle and triggers any associated processes such as enabling public access to items in the bundle at publication time." produces: - "application/json" consumes: - "application/json" responses: 200: description: "The state of the bundle that has been updated" headers: ETag: description: The RFC9110 ETag header field. Defines the unique entity tag for the current state of the resource. This is used for setting the `If-Match` and `If-None-Match` headers on subsequent requests. type: string pattern: ^(?:W/)?"(?:[!#-~])+"$ Cache-Control: description: The RFC9111 Cache-Control header field for the response which instructs how to handle caching the resource. type: string schema: $ref: "#/definitions/Bundle" 400: $ref: "#/responses/InvalidRequest" 401: $ref: "#/responses/UnauthorisedError" 403: $ref: "#/responses/ForbiddenError" 404: $ref: "#/responses/NotFound" 409: $ref: "#/responses/Conflict" 500: $ref: "#/responses/InternalError" /bundle-events: get: parameters: - $ref: "#/parameters/bundle_id_filter" - $ref: "#/parameters/after_filter" - $ref: "#/parameters/before_filter" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" tags: - "Private" summary: "List the audit events for bundles." description: "Audit log of bundle changes and views." produces: - "application/json" responses: 200: description: The list of change audit events for the bundle. headers: ETag: description: The RFC9110 ETag header field. Defines the unique entity tag for the current state of the resource. This is used for setting the `If-Match` and `If-None-Match` headers on subsequent requests. type: string pattern: ^(?:W/)?"(?:[!#-~])+"$ Cache-Control: description: The RFC9111 Cache-Control header field for the response which instructs how to handle caching the resource. type: string schema: $ref: "#/definitions/EventsList" 400: $ref: "#/responses/InvalidRequest" 401: $ref: "#/responses/UnauthorisedError" 403: $ref: "#/responses/ForbiddenError" 404: $ref: "#/responses/NotFound" 500: $ref: "#/responses/InternalError" /health: get: tags: - Private summary: "Returns API's health status" description: "Returns health status of the API and checks on dependent services" security: - {} produces: - application/json responses: 200: description: "Successfully returns OK status with checks of dependent services" schema: $ref: "#/definitions/Health" 429: description: "Services warming up or degraded (at least one check in WARNING or CRITICAL status)" schema: $ref: "#/definitions/Health" 500: description: Service is failing having at least one check with a CRITICAL status having exceeded the recovery grace period. schema: $ref: "#/definitions/Health" responses: Conflict: description: | Change rejected due to a conflict with the current resource state. A common cause is attempting to change a bundle that is already locked pending publication or has already been published. schema: $ref: "#/definitions/ErrorList" ForbiddenError: description: "Access denied." InternalError: description: "Failed to process the request due to an internal error." InvalidRequest: description: "Unable to process request due to a malformed or invalid request body or query parameter." schema: $ref: "#/definitions/ErrorList" MethodNotSupported: description: "Attempted to call an endpoint that is not supported for this API." NotFound: description: "The requested resource does not exist." schema: $ref: "#/definitions/ErrorList" UnauthorisedError: description: "Authentication information is missing or invalid." definitions: Bundles: description: "A list of bundles" type: object allOf: - $ref: "#/definitions/PaginationFields" - type: object properties: items: type: array items: $ref: "#/definitions/Bundle" Bundle: description: "A model for the response body when retrieving a bundle" type: object required: - bundle_type - state - title - managed_by properties: bundle_type: description: "The type of bundle." type: string enum: - MANUAL - SCHEDULED example: SCHEDULED created_by: description: "The user that created the bundle, taken from the auth token supplied. This should only be set on initial creation of the bundle." readOnly: true type: object required: - email properties: email: description: The email of the user who created the bundle. type: string example: "publisher@ons.gov.uk" created_at: description: "The ISO8601 date-time the bundle was created at." type: string format: date-time readOnly: true example: "2025-04-04T07:00:00.000Z" id: type: string description: "The bundle ID" readOnly: true minLength: 1 maxLength: 100 pattern: "^[a-z0-9]+(-[a-z0-9]+)*$" example: "9e4e3628-fc85-48cd-80ad-e005d9d283ff" last_updated_by: description: "The user that last updated the bundle, taken from the auth token supplied." readOnly: true type: object required: - email properties: email: description: The email of the user who updated the bundle. type: string example: "publisher@ons.gov.uk" preview_teams: description: "A list of teams who have permissions to view the dataset series in the bundle." type: array items: type: object required: - id properties: id: description: The preview team ID. type: string minLength: 1 pattern: "^[a-z0-9]+(-[a-z0-9]+)*$" example: 1253e849-01fd-4662-bee2-63253538da93 scheduled_at: description: "The ISO8601 date-time the bundle is scheduled to publish at." type: string format: date-time example: "2025-04-04T07:00:00.000Z" state: $ref: "#/definitions/BundleState" title: type: string description: "The title of the bundle" minLength: 1 example: "CPI March 2025" updated_at: description: "The ISO8601 date-time the bundle was last updated at." type: string readOnly: true format: date-time example: "2025-04-04T07:00:00.000Z" managed_by: description: "The system that created and manages the bundle" type: string enum: - WAGTAIL - DATA-ADMIN example: WAGTAIL Contents: description: "A list of contents related to a bundle" type: object allOf: - $ref: "#/definitions/PaginationFields" - type: object properties: items: type: array items: $ref: "#/definitions/ContentItem" ContentItem: description: "A model which holds information about the datasets to be published as part of the bundle" type: object required: - content_type - metadata properties: bundle_id: description: The ID of the bundle the content item is associated with. type: string readOnly: true minLength: 1 maxLength: 100 pattern: "^[a-z0-9]+(-[a-z0-9]+)*$" example: "9e4e3628-fc85-48cd-80ad-e005d9d283ff" content_type: description: The type of content the item is. type: string enum: - DATASET metadata: description: The metadata for the content item. type: object properties: dataset_id: type: string description: "The dataset ID of the item in the bundle" minLength: 1 example: "cpih" edition_id: type: string description: "The edition ID of the dataset item in the bundle" minLength: 1 example: "march" title: description: "The title of the dataset item. Pre-release, this field will be hydrated from the dataset API when requested. Post-release, the bundle API will store a snapshot of the dataset metadata to be returned on subsequent requests." type: string readOnly: true example: "Consumer Prices Index" version_id: type: integer description: "The version ID of the dataset item in the bundle" minimum: 1 example: 1 id: type: string readOnly: true description: "An auto generated ID field to identify the item" example: "de3bc0b6-d6c4-4e20-917e-95d7ea8c91dc" state: description: "The approval status of the item. Pre-release, this field will be hydrated from the dataset API when requested. Post-release, the bundle API will store a snapshot of the dataset metadata to be returned on subsequent requests." type: string readOnly: true enum: - APPROVED - PUBLISHED example: PUBLISHED links: description: Navigational links for onward actions related to the content item. type: object readOnly: true properties: edit: description: "The URL to the admin page to make changes to the content item." type: string format: url minLength: 1 example: "https://publishing.ons.gov.uk/data-admin/series/cpih/editions/time-series/versions/1" preview: description: "The URL to the preview page for the content item." type: string format: url minLength: 1 example: "https://publishing.ons.gov.uk/inflationandpriceindices/datasets/cpih/editions/time-series/versions/1" ErrorList: description: "A list of errors that occurred." type: object properties: errors: type: array items: $ref: "#/definitions/Error" Error: description: "The details of a specific error." type: object properties: code: type: string description: "Code representing the type of error that occurred for use by consuming systems to identify error types." enum: - InternalError - NotFound - BadRequest - Unauthorised - Forbidden - Conflict - MissingParameters - InvalidParameters - JSONMarshalError - JSONUnmarshalError - WriteResponseError description: type: string description: "Human readable description of the error" source: description: The details of which field or parameter the error relates to. Used to return validation errors to 4xx requests. Only one of the properties below can be returned in any single error. type: object properties: field: description: The RFC 6901 JSON Pointer to the JSON field in the request body to which the error applies. type: string example: "/preview_teams/0" parameter: description: The path or query parameter to which the error applies. type: string example: "limit" header: description: The header to which the error applies. type: string example: If-Match Event: description: Details of a specific change event forming part of the change and audit log for a bundle. type: object readOnly: true required: - requested_by - action - resource properties: created_at: description: The date and time the event occurred. type: string format: date-time requested_by: description: The user who made the request. type: object required: - id properties: id: description: The ID of the user. type: string example: 0889d599-3f0e-4564-9d6e-9455a6b73da7 email: description: The email of the user. This is only populated if the user is a human user. type: string format: email example: publisher@ons.gov.uk action: description: The action taken by the user. type: string enum: - CREATE - READ - UPDATE - DELETE resource: description: The path of the API resource that was called. type: string example: /bundles/e58e8381-c6b2-4e5a-934c-8cbce9b4dc6f/contents/31fda76c-972e-4f73-a999-f9fc428ba74f data: description: | The state of the resource following a change action. This only applies `create` and `update` actions. This will be either a `Bundle` or `ContentItem` object, but as OpenAPI 2.0 does not support `oneOf`, no schema is shown. type: object example: dataset_id: cpih edition_id: march-2025 item_id: de3bc0b6-d6c4-4e20-917e-95d7ea8c91dc state: published url_path: /datasets/cpih/editions/march-2025/versions/1 EventsList: description: "The list of change events which form the change and audit log for a bundle." type: object readOnly: true allOf: - $ref: "#/definitions/PaginationFields" - type: object properties: items: type: array items: $ref: "#/definitions/Event" Health: type: object properties: status: type: string description: "The status of the API" enum: ["OK", "WARNING", "CRITICAL"] version: type: object properties: build_time: type: string description: "The build date and time of the API" example: "2020-06-11T12:49:20+01:00" git_commit: type: string description: "The git commit hash of the API" example: "7c2febbf2b818175112478d4ffbadbee1b654f63" language: type: string description: "The programming language used to implement API" example: "go" language_version: type: string description: "The version of the programming language used to implement API" example: "go1.14.3" version: type: string description: "The version of API" example: "1.0.0" uptime: type: string description: "The uptime of API" example: "34516" start_time: type: string description: "The start date and time of API running" example: "2020-06-11T11:49:21.520922Z" checks: type: array items: $ref: "#/definitions/HealthChecker" HealthChecker: type: object properties: name: type: string description: "The name of external service used by API" enum: ["mongodb"] status: type: string description: "The status of the external service" enum: ["OK", "WARNING", "CRITICAL"] message: type: string description: "The message status of the external service" example: "mongodb is OK" last_checked: type: string description: "The last health check date and time of the external service" example: "2020-06-11T11:49:50.330089Z" last_success: type: string description: "The last successful health check date and time of the external service" example: "2020-06-11T11:49:50.330089Z" last_failure: type: string description: "The last failed health check date and time of the external service" example: "2019-09-22T11:48:51.0000001Z" PaginationFields: type: object properties: count: description: "The number of items returned." readOnly: true type: integer example: 20 limit: description: "The number of items requested." type: integer default: 20 minimum: 0 maximum: 1000 offset: description: "The offset of the first item to retrieve, starting at 0. Use this parameter as a pagination mechanism along with the limit parameter" type: integer example: 0 default: 0 total_count: description: "The total number of items available." readOnly: true type: integer example: 123 BundleState: description: | The current workflow state of the bundle as a whole. The possible states are: * `DRAFT `: Bundle has been created and is being populated with content changes. * `IN_REVIEW`: Bundle has been submitted for review. * `APPROVED`: Bundle has been approved and is awaiting release. * `PUBLISHED `: Bundle has been published and is now public. type: string enum: - DRAFT - IN_REVIEW - APPROVED - PUBLISHED example: APPROVED default: DRAFT