{
  "openapi": "3.1.2",
  "info": {
    "title": "API Specification registry",
    "description": "Enturs central registry of OpenAPI specifications",
    "termsOfService": "https://developer.entur.no/terms-of-service",
    "contact": {
      "name": "API Support",
      "url": "https://entur.no",
      "email": "support@entur.no"
    },
    "version": "2026.11.0",
    "summary": "Enturs central registry of OpenAPI specifications"
  },
  "servers": [
    {
      "url": "https://api.entur.io/api-spec-registry",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "API specifications"
    }
  ],
  "paths": {
    "/v1/specs": {
      "get": {
        "tags": [
          "API specifications"
        ],
        "summary": "Get specifications",
        "description": "Get all specifications stored in the registry.",
        "operationId": "getSpecs",
        "parameters": [
          {
            "name": "maxVersionsPerSpec",
            "in": "query",
            "description": "How many of the newest versions to fetch for each spec",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "integer",
              "default": 5,
              "maximum": 10,
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Spec"
                  }
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "API specifications"
        ],
        "summary": "Upload specification",
        "description": "Upload a specification to the registry.",
        "operationId": "uploadSpec",
        "parameters": [
          {
            "name": "dryRun",
            "in": "query",
            "description": "If true, the specification will not be stored, but all the validation logic will be performed.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "requestBody": {
          "description": "Specification with metadata",
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "spec": {},
                  "changelog": {
                    "type": "array",
                    "items": {}
                  },
                  "metadata": {
                    "$ref": "#/components/schemas/UploadMetadata"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Uploaded specification contained changes from the current version"
          },
          "204": {
            "description": "Uploaded specification was identical to the current version"
          },
          "400": {
            "description": "Uploaded specification was invalid",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          }
        },
        "security": [
          {
            "jwt": []
          }
        ],
        "x-entur-permissions": {
          "value": "api-spec-registry.api-specs:opprett"
        }
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/ET-Client-Name"
        },
        {
          "$ref": "#/components/parameters/X-Correlation-Id"
        }
      ]
    }
  },
  "components": {
    "schemas": {
      "UploadMetadata": {
        "type": "object",
        "examples": [
          {
            "repository": "api-spec-registry"
          }
        ],
        "properties": {
          "repository": {
            "type": "string",
            "examples": [
              "api-spec-registry"
            ]
          },
          "github": {
            "type": "object",
            "properties": {
              "sha": {
                "type": "string"
              },
              "ref": {
                "type": "string"
              },
              "runId": {
                "type": "string"
              }
            },
            "required": [
              "ref",
              "runId",
              "sha"
            ]
          }
        },
        "required": [
          "repository"
        ]
      },
      "Spec": {
        "type": "object",
        "examples": [
          {
            "id": "api-spec-registry"
          }
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "api-spec-registry"
            ]
          },
          "owner": {
            "type": "string",
            "description": "The team that owns the spec",
            "examples": [
              "team-api"
            ]
          },
          "repository": {
            "type": "string",
            "description": "The repository where the spec is defined",
            "examples": [
              "api-spec-registry"
            ]
          }
        },
        "required": [
          "id",
          "owner",
          "repository"
        ]
      },
      "ProblemDetail": {
        "type": "object",
        "description": "Problem Details for HTTP APIs (RFC 9457)",
        "examples": [
          {
            "title": "API specification is invalid",
            "status": 400
          }
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "A URI reference that identifies the problem type",
            "examples": [
              "https://example.com/probs/out-of-credit"
            ]
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type",
            "examples": [
              "You do not have enough credit."
            ]
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "description": "The HTTP status code generated by the origin server",
            "examples": [
              403
            ]
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence",
            "examples": [
              "Your current balance is 30, but that costs 50."
            ]
          },
          "instance": {
            "type": "string",
            "description": "A URI reference that identifies the specific occurrence",
            "examples": [
              "https://example.net/account/12345/msgs/abc"
            ]
          }
        },
        "required": [
          "status",
          "title"
        ]
      }
    },
    "parameters": {
      "ET-Client-Name": {
        "name": "ET-Client-Name",
        "in": "header",
        "description": "Entur Client Header.\nIt is required that all consumers identify themselves by using this header.\nEntur will deploy strict rate-limiting policies on API-consumers who do not identify with a header and reserves the right to block unidentified consumers.\nThe structure of ET-Client-Name should be: `<company>-<application>`.",
        "required": false,
        "style": "simple",
        "explode": false,
        "schema": {
          "type": "string"
        }
      },
      "X-Correlation-Id": {
        "name": "X-Correlation-Id",
        "in": "header",
        "description": "Correlation id",
        "required": false,
        "style": "simple",
        "explode": false,
        "schema": {
          "type": "string"
        }
      }
    },
    "securitySchemes": {
      "jwt": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  }
}