openapi: 3.1.0
info:
  title: Openchamber
  description: 'API for accessing Dutch business and address data: BAG addresses, KVK companies, and LEI entities.'
  version: 1.0.0
  contact:
    name: Openchamber
    email: openchamber@webmethod.eu
  license:
    name: PROPRIETARY
servers:
  -
    url: 'https://openchamber.nl'
tags:
  -
    name: 'Basisregistratie Adressen en Gebouwen (BAG)'
    description: "\nAPIs for querying Dutch address data from the Kadaster BAG (Basisregistratie Adressen en Gebouwen).\nAll endpoints require authentication via API key with specific permissions."
  -
    name: 'Kamer van Koophandel'
    description: "\nAPIs for managing and querying Dutch Chamber of Commerce (KVK) company data.\nAll endpoints require authentication via API key with specific permissions."
  -
    name: 'Legal Entity Identifier (LEI)'
    description: "\nAPIs for managing and querying Legal Entity Identifier (LEI) entities.\nAll endpoints require authentication via API key."
components:
  securitySchemes:
    default:
      type: apiKey
      name: X-API-Key
      in: header
      description: 'You can get your API key from your account dashboard. Different endpoints may require different API key permissions (kvk:read, kvk:search, lei:read).'
security:
  -
    default: []
paths:
  /api/bag:
    get:
      summary: 'List BAG addresses'
      operationId: listBAGAddresses
      description: 'Retrieve a paginated list of BAG addresses from the local database with filtering and sorting options.'
      parameters:
        -
          in: query
          name: postal_code
          description: 'Filter by postal code (with or without space).'
          example: 1012AB
          required: false
          schema:
            type: string
            description: 'Filter by postal code (with or without space).'
            example: 1012AB
        -
          in: query
          name: house_number
          description: 'Filter by house number.'
          example: 123
          required: false
          schema:
            type: integer
            description: 'Filter by house number.'
            example: 123
        -
          in: query
          name: street_name
          description: 'Search by street name (partial match).'
          example: Keizersgracht
          required: false
          schema:
            type: string
            description: 'Search by street name (partial match).'
            example: Keizersgracht
        -
          in: query
          name: city
          description: 'Filter by city (partial match).'
          example: Amsterdam
          required: false
          schema:
            type: string
            description: 'Filter by city (partial match).'
            example: Amsterdam
        -
          in: query
          name: municipality
          description: 'Filter by municipality.'
          example: Amsterdam
          required: false
          schema:
            type: string
            description: 'Filter by municipality.'
            example: Amsterdam
        -
          in: query
          name: province
          description: 'Filter by province.'
          example: Noord-Holland
          required: false
          schema:
            type: string
            description: 'Filter by province.'
            example: Noord-Holland
        -
          in: query
          name: in_use
          description: 'Filter by in-use status.'
          example: true
          required: false
          schema:
            type: boolean
            description: 'Filter by in-use status.'
            example: true
        -
          in: query
          name: sort
          description: 'Sort field. Available: street_name, city, postal_code, house_number.'
          example: street_name
          required: false
          schema:
            type: string
            description: 'Sort field. Available: street_name, city, postal_code, house_number.'
            example: street_name
        -
          in: query
          name: order
          description: 'Sort order (asc or desc).'
          example: asc
          required: false
          schema:
            type: string
            description: 'Sort order (asc or desc).'
            example: asc
        -
          in: query
          name: per_page
          description: 'Number of results per page (default: 15, max: 100).'
          example: 25
          required: false
          schema:
            type: integer
            description: 'Number of results per page (default: 15, max: 100).'
            example: 25
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      id: 01J9X...
                      bag_id: '0363200000000001'
                      postal_code: 1012AB
                      house_number: '1'
                      house_letter: null
                      house_number_addition: null
                      street_name: Keizersgracht
                      city: Amsterdam
                      municipality: Amsterdam
                      province: Noord-Holland
                      full_address: 'Keizersgracht 1 1012AB Amsterdam'
                      coordinates:
                        latitude: 52.370216
                        longitude: 4.895168
                      last_synced_at: '2023-11-20T10:30:00Z'
                  links:
                    first: 'http://example.com/api/bag?page=1'
                    last: 'http://example.com/api/bag?page=5'
                    prev: null
                    next: 'http://example.com/api/bag?page=2'
                  meta:
                    current_page: 1
                    per_page: 15
                    total: 73
                properties:
                  data:
                    type: array
                    example:
                      -
                        id: 01J9X...
                        bag_id: '0363200000000001'
                        postal_code: 1012AB
                        house_number: '1'
                        house_letter: null
                        house_number_addition: null
                        street_name: Keizersgracht
                        city: Amsterdam
                        municipality: Amsterdam
                        province: Noord-Holland
                        full_address: 'Keizersgracht 1 1012AB Amsterdam'
                        coordinates:
                          latitude: 52.370216
                          longitude: 4.895168
                        last_synced_at: '2023-11-20T10:30:00Z'
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          example: 01J9X...
                        bag_id:
                          type: string
                          example: '0363200000000001'
                        postal_code:
                          type: string
                          example: 1012AB
                        house_number:
                          type: string
                          example: '1'
                        house_letter:
                          type: string
                          example: null
                        house_number_addition:
                          type: string
                          example: null
                        street_name:
                          type: string
                          example: Keizersgracht
                        city:
                          type: string
                          example: Amsterdam
                        municipality:
                          type: string
                          example: Amsterdam
                        province:
                          type: string
                          example: Noord-Holland
                        full_address:
                          type: string
                          example: 'Keizersgracht 1 1012AB Amsterdam'
                        coordinates:
                          type: object
                          properties:
                            latitude:
                              type: number
                              example: 52.370216
                            longitude:
                              type: number
                              example: 4.895168
                        last_synced_at:
                          type: string
                          example: '2023-11-20T10:30:00Z'
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                        example: 'http://example.com/api/bag?page=1'
                      last:
                        type: string
                        example: 'http://example.com/api/bag?page=5'
                      prev:
                        type: string
                        example: null
                      next:
                        type: string
                        example: 'http://example.com/api/bag?page=2'
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                        example: 1
                      per_page:
                        type: integer
                        example: 15
                      total:
                        type: integer
                        example: 73
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Invalid API key'
                properties:
                  message:
                    type: string
                    example: 'Invalid API key'
      tags:
        - 'Basisregistratie Adressen en Gebouwen (BAG)'
      security: []
  /api/bag/search:
    get:
      summary: 'Search BAG addresses'
      operationId: searchBAGAddresses
      description: "Search for addresses using postal code, house number, street name, or city.\nResults are cached locally for faster subsequent queries."
      parameters:
        -
          in: query
          name: postal_code
          description: 'Postal code (required if not using street search).'
          example: 1012AB
          required: false
          schema:
            type: string
            description: 'Postal code (required if not using street search).'
            example: 1012AB
        -
          in: query
          name: house_number
          description: 'House number (optional, refines postal code search).'
          example: 1
          required: false
          schema:
            type: integer
            description: 'House number (optional, refines postal code search).'
            example: 1
        -
          in: query
          name: house_letter
          description: 'House letter (optional).'
          example: A
          required: false
          schema:
            type: string
            description: 'House letter (optional).'
            example: A
        -
          in: query
          name: house_number_addition
          description: 'House number addition (optional).'
          example: bis
          required: false
          schema:
            type: string
            description: 'House number addition (optional).'
            example: bis
        -
          in: query
          name: street_name
          description: 'Street name (required if not using postal code).'
          example: Keizersgracht
          required: false
          schema:
            type: string
            description: 'Street name (required if not using postal code).'
            example: Keizersgracht
        -
          in: query
          name: city
          description: 'City name (required if using street search).'
          example: Amsterdam
          required: false
          schema:
            type: string
            description: 'City name (required if using street search).'
            example: Amsterdam
      responses:
        200:
          description: 'Success with postal code'
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      id: 01J9X...
                      bag_id: '0363200000000001'
                      postal_code: 1012AB
                      house_number: '1'
                      street_name: Keizersgracht
                      city: Amsterdam
                      full_address: 'Keizersgracht 1 1012AB Amsterdam'
                      coordinates:
                        latitude: 52.370216
                        longitude: 4.895168
                  meta:
                    search_type: postal_code
                    total: 1
                properties:
                  data:
                    type: array
                    example:
                      -
                        id: 01J9X...
                        bag_id: '0363200000000001'
                        postal_code: 1012AB
                        house_number: '1'
                        street_name: Keizersgracht
                        city: Amsterdam
                        full_address: 'Keizersgracht 1 1012AB Amsterdam'
                        coordinates:
                          latitude: 52.370216
                          longitude: 4.895168
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          example: 01J9X...
                        bag_id:
                          type: string
                          example: '0363200000000001'
                        postal_code:
                          type: string
                          example: 1012AB
                        house_number:
                          type: string
                          example: '1'
                        street_name:
                          type: string
                          example: Keizersgracht
                        city:
                          type: string
                          example: Amsterdam
                        full_address:
                          type: string
                          example: 'Keizersgracht 1 1012AB Amsterdam'
                        coordinates:
                          type: object
                          properties:
                            latitude:
                              type: number
                              example: 52.370216
                            longitude:
                              type: number
                              example: 4.895168
                  meta:
                    type: object
                    properties:
                      search_type:
                        type: string
                        example: postal_code
                      total:
                        type: integer
                        example: 1
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Invalid API key'
                properties:
                  message:
                    type: string
                    example: 'Invalid API key'
        422:
          description: 'Validation error'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Either postal_code or both street_name and city are required.'
                  errors:
                    postal_code:
                      - 'The postal code field is required when street name is not present.'
                properties:
                  message:
                    type: string
                    example: 'Either postal_code or both street_name and city are required.'
                  errors:
                    type: object
                    properties:
                      postal_code:
                        type: array
                        example:
                          - 'The postal code field is required when street name is not present.'
                        items:
                          type: string
        500:
          description: 'API failure'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'BAG API search failed.'
                properties:
                  message:
                    type: string
                    example: 'BAG API search failed.'
        503:
          description: 'Service unavailable'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'BAG API not configured.'
                properties:
                  message:
                    type: string
                    example: 'BAG API not configured.'
      tags:
        - 'Basisregistratie Adressen en Gebouwen (BAG)'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                postal_code:
                  type: string
                  description: 'This field is required when none of <code>street_name</code> and <code>city</code> are present. Must be at least 6 characters. Must not be greater than 7 characters.'
                  example: bngzmiy
                house_number:
                  type: integer
                  description: 'Must be at least 1.'
                  example: 16
                house_letter:
                  type: string
                  description: 'Must not be greater than 5 characters.'
                  example: d
                house_number_addition:
                  type: string
                  description: 'Must not be greater than 10 characters.'
                  example: ljnikh
                street_name:
                  type: string
                  description: 'This field is required when <code>postal_code</code> is not present. This field is required when <code>city</code> is present. Must be at least 2 characters.'
                  example: wayk
                city:
                  type: string
                  description: 'This field is required when <code>street_name</code> is present. Must be at least 2 characters.'
                  example: cmyu
      security: []
  '/api/bag/{postalCode}/{houseNumber}/{addition}':
    get:
      summary: 'Lookup address by postal code and house number'
      operationId: lookupAddressByPostalCodeAndHouseNumber
      description: 'Convenient endpoint for direct address lookup. Automatically formats postal code and handles additions.'
      parameters: []
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: 01J9X...
                    bag_id: '0363200000000001'
                    postal_code: 1012AB
                    house_number: '1'
                    street_name: Keizersgracht
                    city: Amsterdam
                    full_address: 'Keizersgracht 1 1012AB Amsterdam'
                    coordinates:
                      latitude: 52.370216
                      longitude: 4.895168
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: 01J9X...
                      bag_id:
                        type: string
                        example: '0363200000000001'
                      postal_code:
                        type: string
                        example: 1012AB
                      house_number:
                        type: string
                        example: '1'
                      street_name:
                        type: string
                        example: Keizersgracht
                      city:
                        type: string
                        example: Amsterdam
                      full_address:
                        type: string
                        example: 'Keizersgracht 1 1012AB Amsterdam'
                      coordinates:
                        type: object
                        properties:
                          latitude:
                            type: number
                            example: 52.370216
                          longitude:
                            type: number
                            example: 4.895168
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Invalid API key'
                properties:
                  message:
                    type: string
                    example: 'Invalid API key'
        404:
          description: 'Not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Address not found.'
                properties:
                  message:
                    type: string
                    example: 'Address not found.'
        503:
          description: 'Service unavailable'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'BAG API not configured.'
                properties:
                  message:
                    type: string
                    example: 'BAG API not configured.'
      tags:
        - 'Basisregistratie Adressen en Gebouwen (BAG)'
      security: []
    parameters:
      -
        in: path
        name: postalCode
        description: 'Postal code (with or without space).'
        example: 1012AB
        required: true
        schema:
          type: string
      -
        in: path
        name: houseNumber
        description: 'House number.'
        example: 1
        required: true
        schema:
          type: integer
      -
        in: path
        name: addition
        description: 'Optional parameter. House letter or addition (optional).'
        required: true
        schema:
          type: string
        examples:
          omitted:
            summary: 'When the value is omitted'
            value: ''
          present:
            summary: 'When the value is present'
            value: A
  '/api/bag/{bagId}':
    get:
      summary: 'Get BAG address by ID'
      operationId: getBAGAddressByID
      description: "Retrieve a specific BAG address by its BAG ID. Checks local cache first,\nfetches from BAG API if not found or data is stale (older than 30 days)."
      parameters: []
      responses:
        200:
          description: Success
          content:
            text/plain:
              schema:
                type: string
                example: "{\n  \"data\": {\n    \"id\": \"01J9X...\",\n    \"bag_id\": \"0363200000000001\",\n    \"postal_code\": \"1012AB\",\n    \"house_number\": \"1\",\n    \"house_letter\": null,\n    \"house_number_addition\": null,\n    \"street_name\": \"Keizersgracht\",\n    \"official_street_name\": \"Keizersgracht\",\n    \"city\": \"Amsterdam\",\n    \"municipality\": \"Amsterdam\",\n    \"province\": \"Noord-Holland\",\n    \"object_type\": \"verblijfsobject\",\n    \"status\": \"Naamgeving uitgegeven\",\n    \"in_use\": true,\n    \"full_address\": \"Keizersgracht 1 1012AB Amsterdam\",\n    \"coordinates\": {\n      \"latitude\": 52.370216,\n      \"longitude\": 4.895168\n    },\n    \"full_data\": {...},\n    \"last_synced_at\": \"2023-11-20T10:30:00Z\"\n  }\n}"
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Invalid API key'
                properties:
                  message:
                    type: string
                    example: 'Invalid API key'
        404:
          description: 'Not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Address not found in BAG API.'
                properties:
                  message:
                    type: string
                    example: 'Address not found in BAG API.'
        503:
          description: 'Service unavailable'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'BAG API not configured and address not found in cache.'
                properties:
                  message:
                    type: string
                    example: 'BAG API not configured and address not found in cache.'
      tags:
        - 'Basisregistratie Adressen en Gebouwen (BAG)'
      security: []
    parameters:
      -
        in: path
        name: bagId
        description: 'The BAG address object ID.'
        example: '0363200000000001'
        required: true
        schema:
          type: string
  /api/kvk:
    get:
      summary: 'List KVK companies'
      operationId: listKVKCompanies
      description: 'Retrieve a paginated list of KVK companies from the local database with filtering and sorting options.'
      parameters:
        -
          in: query
          name: kvk_number
          description: 'Filter by exact KVK number (8 digits).'
          example: '12345678'
          required: false
          schema:
            type: string
            description: 'Filter by exact KVK number (8 digits).'
            example: '12345678'
        -
          in: query
          name: name
          description: 'Search by company name (partial match in naam or statutaire_naam).'
          example: ACME
          required: false
          schema:
            type: string
            description: 'Search by company name (partial match in naam or statutaire_naam).'
            example: ACME
        -
          in: query
          name: city
          description: 'Filter by city/place (partial match).'
          example: Amsterdam
          required: false
          schema:
            type: string
            description: 'Filter by city/place (partial match).'
            example: Amsterdam
        -
          in: query
          name: postal_code
          description: 'Filter by exact postal code.'
          example: 1012AB
          required: false
          schema:
            type: string
            description: 'Filter by exact postal code.'
            example: 1012AB
        -
          in: query
          name: active
          description: 'Filter by active status.'
          example: true
          required: false
          schema:
            type: boolean
            description: 'Filter by active status.'
            example: true
        -
          in: query
          name: type
          description: 'Filter by company type.'
          example: rechtspersoon
          required: false
          schema:
            type: string
            description: 'Filter by company type.'
            example: rechtspersoon
        -
          in: query
          name: sort
          description: 'Sort field. Available: name, kvk_number, city, postal_code, active, registration_date.'
          example: name
          required: false
          schema:
            type: string
            description: 'Sort field. Available: name, kvk_number, city, postal_code, active, registration_date.'
            example: name
        -
          in: query
          name: order
          description: 'Sort order (asc or desc).'
          example: asc
          required: false
          schema:
            type: string
            description: 'Sort order (asc or desc).'
            example: asc
        -
          in: query
          name: per_page
          description: 'Number of results per page (default: 15, max: 100).'
          example: 25
          required: false
          schema:
            type: integer
            description: 'Number of results per page (default: 15, max: 100).'
            example: 25
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      kvk_nummer: '12345678'
                      naam: 'Example Company B.V.'
                      statutaire_naam: 'Example Company Besloten Vennootschap'
                      vestigingsnummer: '000012345678'
                      actief: true
                      type: rechtspersoon
                      straatnaam: Keizersgracht
                      huisnummer: '123'
                      postcode: 1012AB
                      plaats: Amsterdam
                      rechtsvorm: 'Besloten Vennootschap'
                      rsin: '123456789'
                      formele_registratiedatum: '2020-01-15'
                      last_synced_at: '2023-11-20T10:30:00Z'
                  links:
                    first: 'http://example.com/api/kvk?page=1'
                    last: 'http://example.com/api/kvk?page=5'
                    prev: null
                    next: 'http://example.com/api/kvk?page=2'
                  meta:
                    current_page: 1
                    per_page: 15
                    total: 73
                properties:
                  data:
                    type: array
                    example:
                      -
                        kvk_nummer: '12345678'
                        naam: 'Example Company B.V.'
                        statutaire_naam: 'Example Company Besloten Vennootschap'
                        vestigingsnummer: '000012345678'
                        actief: true
                        type: rechtspersoon
                        straatnaam: Keizersgracht
                        huisnummer: '123'
                        postcode: 1012AB
                        plaats: Amsterdam
                        rechtsvorm: 'Besloten Vennootschap'
                        rsin: '123456789'
                        formele_registratiedatum: '2020-01-15'
                        last_synced_at: '2023-11-20T10:30:00Z'
                    items:
                      type: object
                      properties:
                        kvk_nummer:
                          type: string
                          example: '12345678'
                        naam:
                          type: string
                          example: 'Example Company B.V.'
                        statutaire_naam:
                          type: string
                          example: 'Example Company Besloten Vennootschap'
                        vestigingsnummer:
                          type: string
                          example: '000012345678'
                        actief:
                          type: boolean
                          example: true
                        type:
                          type: string
                          example: rechtspersoon
                        straatnaam:
                          type: string
                          example: Keizersgracht
                        huisnummer:
                          type: string
                          example: '123'
                        postcode:
                          type: string
                          example: 1012AB
                        plaats:
                          type: string
                          example: Amsterdam
                        rechtsvorm:
                          type: string
                          example: 'Besloten Vennootschap'
                        rsin:
                          type: string
                          example: '123456789'
                        formele_registratiedatum:
                          type: string
                          example: '2020-01-15'
                        last_synced_at:
                          type: string
                          example: '2023-11-20T10:30:00Z'
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                        example: 'http://example.com/api/kvk?page=1'
                      last:
                        type: string
                        example: 'http://example.com/api/kvk?page=5'
                      prev:
                        type: string
                        example: null
                      next:
                        type: string
                        example: 'http://example.com/api/kvk?page=2'
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                        example: 1
                      per_page:
                        type: integer
                        example: 15
                      total:
                        type: integer
                        example: 73
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Invalid API key'
                properties:
                  message:
                    type: string
                    example: 'Invalid API key'
      tags:
        - 'Kamer van Koophandel'
      security: []
  /api/kvk/search:
    get:
      summary: 'Search KVK companies via API'
      operationId: searchKVKCompaniesViaAPI
      description: "Search for companies directly via the KVK API and cache the results locally.\nRequires KVK API to be configured."
      parameters:
        -
          in: query
          name: name
          description: 'Company name to search for (minimum 2 characters).'
          example: ACME
          required: false
          schema:
            type: string
            description: 'Company name to search for (minimum 2 characters).'
            example: ACME
        -
          in: query
          name: kvk_number
          description: 'KVK number to search for (exactly 8 digits).'
          example: '12345678'
          required: false
          schema:
            type: string
            description: 'KVK number to search for (exactly 8 digits).'
            example: '12345678'
        -
          in: query
          name: city
          description: 'City/place to filter by.'
          example: Amsterdam
          required: false
          schema:
            type: string
            description: 'City/place to filter by.'
            example: Amsterdam
        -
          in: query
          name: postal_code
          description: 'Postal code to filter by.'
          example: 1012AB
          required: false
          schema:
            type: string
            description: 'Postal code to filter by.'
            example: 1012AB
        -
          in: query
          name: house_number
          description: 'House number to filter by.'
          example: 123
          required: false
          schema:
            type: integer
            description: 'House number to filter by.'
            example: 123
        -
          in: query
          name: page
          description: 'Page number (1-100).'
          example: 1
          required: false
          schema:
            type: integer
            description: 'Page number (1-100).'
            example: 1
        -
          in: query
          name: results_per_page
          description: 'Results per page (1-100).'
          example: 10
          required: false
          schema:
            type: integer
            description: 'Results per page (1-100).'
            example: 10
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      kvk_nummer: '12345678'
                      naam: 'Example Company B.V.'
                      vestigingsnummer: '000012345678'
                      actief: true
                      type: rechtspersoon
                      straatnaam: Keizersgracht
                      huisnummer: '123'
                      postcode: 1012AB
                      plaats: Amsterdam
                  meta:
                    page: 1
                    results_per_page: 10
                    total: 73
                  links:
                    previous: null
                    next: 'https://api.kvk.nl/api/v1/zoeken?page=2'
                properties:
                  data:
                    type: array
                    example:
                      -
                        kvk_nummer: '12345678'
                        naam: 'Example Company B.V.'
                        vestigingsnummer: '000012345678'
                        actief: true
                        type: rechtspersoon
                        straatnaam: Keizersgracht
                        huisnummer: '123'
                        postcode: 1012AB
                        plaats: Amsterdam
                    items:
                      type: object
                      properties:
                        kvk_nummer:
                          type: string
                          example: '12345678'
                        naam:
                          type: string
                          example: 'Example Company B.V.'
                        vestigingsnummer:
                          type: string
                          example: '000012345678'
                        actief:
                          type: boolean
                          example: true
                        type:
                          type: string
                          example: rechtspersoon
                        straatnaam:
                          type: string
                          example: Keizersgracht
                        huisnummer:
                          type: string
                          example: '123'
                        postcode:
                          type: string
                          example: 1012AB
                        plaats:
                          type: string
                          example: Amsterdam
                  meta:
                    type: object
                    properties:
                      page:
                        type: integer
                        example: 1
                      results_per_page:
                        type: integer
                        example: 10
                      total:
                        type: integer
                        example: 73
                  links:
                    type: object
                    properties:
                      previous:
                        type: string
                        example: null
                      next:
                        type: string
                        example: 'https://api.kvk.nl/api/v1/zoeken?page=2'
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Invalid API key'
                properties:
                  message:
                    type: string
                    example: 'Invalid API key'
        422:
          description: 'Validation error'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The name field must be at least 2 characters.'
                  errors:
                    name:
                      - 'The name field must be at least 2 characters.'
                properties:
                  message:
                    type: string
                    example: 'The name field must be at least 2 characters.'
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        example:
                          - 'The name field must be at least 2 characters.'
                        items:
                          type: string
        500:
          description: 'API failure'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'KVK API search failed.'
                properties:
                  message:
                    type: string
                    example: 'KVK API search failed.'
        503:
          description: 'Service unavailable'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'KVK API not configured.'
                properties:
                  message:
                    type: string
                    example: 'KVK API not configured.'
      tags:
        - 'Kamer van Koophandel'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: 'Must be at least 2 characters.'
                  example: bngz
                kvk_number:
                  type: string
                  description: 'Must be 8 characters.'
                  example: miyvdljn
                city:
                  type: string
                  description: ''
                  example: architecto
                postal_code:
                  type: string
                  description: ''
                  example: architecto
                house_number:
                  type: integer
                  description: ''
                  example: 16
                page:
                  type: integer
                  description: 'Must be at least 1. Must not be greater than 100.'
                  example: 22
                results_per_page:
                  type: integer
                  description: 'Must be at least 1. Must not be greater than 100.'
                  example: 7
      security: []
  '/api/kvk/{kvkNummer}':
    get:
      summary: 'Get KVK company by number'
      operationId: getKVKCompanyByNumber
      description: "Retrieve a specific KVK company by its KVK number. Checks local cache first,\nfetches from KVK API if not found or data is stale (older than 30 days).\n\nPriority order: main_establishment > legal_entity > branch\nReturns related records (other types with the same KVK number) in the response."
      parameters: []
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: 01kasb2yqwwr7hn3k5b7d4bwyv
                    kvk_number: '12345678'
                    rsin: '123456789'
                    establishment_number: '000012345678'
                    name: 'Example Company B.V.'
                    statutory_name: 'Example Company Besloten Vennootschap'
                    formal_registration_date: '2020-01-15T00:00:00+00:00'
                    material_registration_date: '2020-01-10T00:00:00+00:00'
                    address:
                      street_name: Keizersgracht
                      house_number: '123'
                      postal_code: 1012AB
                      city: Amsterdam
                    type: main_establishment
                    active: true
                    legal_form: 'Besloten Vennootschap'
                    non_mailing: false
                    is_main_establishment: true
                    total_employees: 25
                    cache:
                      last_synced_at: '2023-11-20T10:30:00+00:00'
                      is_stale: false
                    created_at: '2023-11-20T10:30:00+00:00'
                    updated_at: '2023-11-20T10:30:00+00:00'
                    related:
                      -
                        id: 01kasb2yqwwr7hn3k5b7d4bwyx
                        kvk_number: '12345678'
                        establishment_number: null
                        name: 'Example Company B.V.'
                        type: legal_entity
                        active: true
                        address:
                          street_name: null
                          house_number: null
                          postal_code: null
                          city: null
                        is_main_establishment: false
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: 01kasb2yqwwr7hn3k5b7d4bwyv
                      kvk_number:
                        type: string
                        example: '12345678'
                      rsin:
                        type: string
                        example: '123456789'
                      establishment_number:
                        type: string
                        example: '000012345678'
                      name:
                        type: string
                        example: 'Example Company B.V.'
                      statutory_name:
                        type: string
                        example: 'Example Company Besloten Vennootschap'
                      formal_registration_date:
                        type: string
                        example: '2020-01-15T00:00:00+00:00'
                      material_registration_date:
                        type: string
                        example: '2020-01-10T00:00:00+00:00'
                      address:
                        type: object
                        properties:
                          street_name:
                            type: string
                            example: Keizersgracht
                          house_number:
                            type: string
                            example: '123'
                          postal_code:
                            type: string
                            example: 1012AB
                          city:
                            type: string
                            example: Amsterdam
                      type:
                        type: string
                        example: main_establishment
                      active:
                        type: boolean
                        example: true
                      legal_form:
                        type: string
                        example: 'Besloten Vennootschap'
                      non_mailing:
                        type: boolean
                        example: false
                      is_main_establishment:
                        type: boolean
                        example: true
                      total_employees:
                        type: integer
                        example: 25
                      cache:
                        type: object
                        properties:
                          last_synced_at:
                            type: string
                            example: '2023-11-20T10:30:00+00:00'
                          is_stale:
                            type: boolean
                            example: false
                      created_at:
                        type: string
                        example: '2023-11-20T10:30:00+00:00'
                      updated_at:
                        type: string
                        example: '2023-11-20T10:30:00+00:00'
                      related:
                        type: array
                        example:
                          -
                            id: 01kasb2yqwwr7hn3k5b7d4bwyx
                            kvk_number: '12345678'
                            establishment_number: null
                            name: 'Example Company B.V.'
                            type: legal_entity
                            active: true
                            address:
                              street_name: null
                              house_number: null
                              postal_code: null
                              city: null
                            is_main_establishment: false
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                              example: 01kasb2yqwwr7hn3k5b7d4bwyx
                            kvk_number:
                              type: string
                              example: '12345678'
                            establishment_number:
                              type: string
                              example: null
                            name:
                              type: string
                              example: 'Example Company B.V.'
                            type:
                              type: string
                              example: legal_entity
                            active:
                              type: boolean
                              example: true
                            address:
                              type: object
                              properties:
                                street_name:
                                  type: string
                                  example: null
                                house_number:
                                  type: string
                                  example: null
                                postal_code:
                                  type: string
                                  example: null
                                city:
                                  type: string
                                  example: null
                            is_main_establishment:
                              type: boolean
                              example: false
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Invalid API key'
                properties:
                  message:
                    type: string
                    example: 'Invalid API key'
        404:
          description: 'Not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Company not found in KVK API.'
                properties:
                  message:
                    type: string
                    example: 'Company not found in KVK API.'
        503:
          description: 'Service unavailable'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'KVK API not configured and company not found in cache.'
                properties:
                  message:
                    type: string
                    example: 'KVK API not configured and company not found in cache.'
      tags:
        - 'Kamer van Koophandel'
      security: []
    parameters:
      -
        in: path
        name: kvkNummer
        description: 'The KVK number (8 digits).'
        example: '12345678'
        required: true
        schema:
          type: string
  '/api/kvk/{kvkNummer}/establishments':
    get:
      summary: 'List establishments for a company'
      operationId: listEstablishmentsForACompany
      description: 'Retrieve all establishments (vestigingen) for a specific KVK number.'
      parameters: []
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      establishment_number: '000032242441'
                      name: Webmethod
                      type: main_establishment
                      is_main_establishment: true
                      address:
                        street_name: Pleiadenlaan
                        house_number: '1 145'
                        postal_code: 9742NE
                        city: Groningen
                      active: true
                properties:
                  data:
                    type: array
                    example:
                      -
                        establishment_number: '000032242441'
                        name: Webmethod
                        type: main_establishment
                        is_main_establishment: true
                        address:
                          street_name: Pleiadenlaan
                          house_number: '1 145'
                          postal_code: 9742NE
                          city: Groningen
                        active: true
                    items:
                      type: object
                      properties:
                        establishment_number:
                          type: string
                          example: '000032242441'
                        name:
                          type: string
                          example: Webmethod
                        type:
                          type: string
                          example: main_establishment
                        is_main_establishment:
                          type: boolean
                          example: true
                        address:
                          type: object
                          properties:
                            street_name:
                              type: string
                              example: Pleiadenlaan
                            house_number:
                              type: string
                              example: '1 145'
                            postal_code:
                              type: string
                              example: 9742NE
                            city:
                              type: string
                              example: Groningen
                        active:
                          type: boolean
                          example: true
      tags:
        - 'Kamer van Koophandel'
      security: []
    parameters:
      -
        in: path
        name: kvkNummer
        description: 'The KVK number (8 digits).'
        example: '63314061'
        required: true
        schema:
          type: string
  '/api/kvk/{kvkNummer}/establishments/{establishmentNumber}':
    get:
      summary: 'Get specific establishment'
      operationId: getSpecificEstablishment
      description: 'Retrieve a specific establishment by its establishment number.'
      parameters: []
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    establishment_number: '000032242441'
                    name: Webmethod
                    type: main_establishment
                    address:
                      street_name: Pleiadenlaan
                      house_number: '1 145'
                      postal_code: 9742NE
                      city: Groningen
                    company:
                      kvk_number: '63314061'
                      name: Webmethod
                      legal_form: Eenmanszaak
                properties:
                  data:
                    type: object
                    properties:
                      establishment_number:
                        type: string
                        example: '000032242441'
                      name:
                        type: string
                        example: Webmethod
                      type:
                        type: string
                        example: main_establishment
                      address:
                        type: object
                        properties:
                          street_name:
                            type: string
                            example: Pleiadenlaan
                          house_number:
                            type: string
                            example: '1 145'
                          postal_code:
                            type: string
                            example: 9742NE
                          city:
                            type: string
                            example: Groningen
                      company:
                        type: object
                        properties:
                          kvk_number:
                            type: string
                            example: '63314061'
                          name:
                            type: string
                            example: Webmethod
                          legal_form:
                            type: string
                            example: Eenmanszaak
        404:
          description: 'Not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Establishment not found'
                properties:
                  message:
                    type: string
                    example: 'Establishment not found'
      tags:
        - 'Kamer van Koophandel'
      security: []
    parameters:
      -
        in: path
        name: kvkNummer
        description: 'The KVK number (8 digits).'
        example: '63314061'
        required: true
        schema:
          type: string
      -
        in: path
        name: establishmentNumber
        description: 'The establishment number (12 digits).'
        example: '000032242441'
        required: true
        schema:
          type: string
  /api/lei:
    get:
      summary: 'List LEI entities'
      operationId: listLEIEntities
      description: 'Retrieve a paginated list of LEI entities with optional search and filtering capabilities.'
      parameters:
        -
          in: query
          name: search
          description: 'Search in legal name, LEI code, city, or registration authority entity ID.'
          example: ACME
          required: false
          schema:
            type: string
            description: 'Search in legal name, LEI code, city, or registration authority entity ID.'
            example: ACME
        -
          in: query
          name: country
          description: 'Filter by country code (ISO 3166-1 alpha-2).'
          example: NL
          required: false
          schema:
            type: string
            description: 'Filter by country code (ISO 3166-1 alpha-2).'
            example: NL
        -
          in: query
          name: status
          description: 'Filter by legal entity status.'
          example: ACTIVE
          required: false
          schema:
            type: string
            description: 'Filter by legal entity status.'
            example: ACTIVE
        -
          in: query
          name: legal_form
          description: 'Filter by legal form (partial match).'
          example: BV
          required: false
          schema:
            type: string
            description: 'Filter by legal form (partial match).'
            example: BV
        -
          in: query
          name: postal_code
          description: 'Filter by postal code.'
          example: 1012AB
          required: false
          schema:
            type: string
            description: 'Filter by postal code.'
            example: 1012AB
        -
          in: query
          name: registration_authority_entity_id
          description: 'Filter by registration authority entity ID.'
          example: '12345678'
          required: false
          schema:
            type: string
            description: 'Filter by registration authority entity ID.'
            example: '12345678'
        -
          in: query
          name: city
          description: 'Filter by city name (partial match).'
          example: Amsterdam
          required: false
          schema:
            type: string
            description: 'Filter by city name (partial match).'
            example: Amsterdam
        -
          in: query
          name: per_page
          description: 'Number of results per page (default: 15, max: 100).'
          example: 25
          required: false
          schema:
            type: integer
            description: 'Number of results per page (default: 15, max: 100).'
            example: 25
        -
          in: query
          name: sort
          description: 'Field to sort by. Available: legal_name, lei, legal_entity_status, entity_creation_date, last_public_update_date, legal_address_country, legal_address_city.'
          example: legal_name
          required: false
          schema:
            type: string
            description: 'Field to sort by. Available: legal_name, lei, legal_entity_status, entity_creation_date, last_public_update_date, legal_address_country, legal_address_city.'
            example: legal_name
        -
          in: query
          name: order
          description: 'Sort order (asc or desc).'
          example: asc
          required: false
          schema:
            type: string
            description: 'Sort order (asc or desc).'
            example: asc
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      lei: 724500VKKSH9QOLTFR81
                      legal_name: 'Example Company B.V.'
                      legal_entity_status: ACTIVE
                      legal_form: 'Besloten Vennootschap'
                      legal_address_country: NL
                      legal_address_city: Amsterdam
                      legal_address_postal_code: 1012AB
                      registration_authority_entity_id: '12345678'
                      entity_creation_date: '2020-01-15'
                      last_public_update_date: '2023-11-20T10:30:00Z'
                  links:
                    first: 'http://example.com/api/lei?page=1'
                    last: 'http://example.com/api/lei?page=5'
                    prev: null
                    next: 'http://example.com/api/lei?page=2'
                  meta:
                    current_page: 1
                    per_page: 15
                    total: 73
                properties:
                  data:
                    type: array
                    example:
                      -
                        lei: 724500VKKSH9QOLTFR81
                        legal_name: 'Example Company B.V.'
                        legal_entity_status: ACTIVE
                        legal_form: 'Besloten Vennootschap'
                        legal_address_country: NL
                        legal_address_city: Amsterdam
                        legal_address_postal_code: 1012AB
                        registration_authority_entity_id: '12345678'
                        entity_creation_date: '2020-01-15'
                        last_public_update_date: '2023-11-20T10:30:00Z'
                    items:
                      type: object
                      properties:
                        lei:
                          type: string
                          example: 724500VKKSH9QOLTFR81
                        legal_name:
                          type: string
                          example: 'Example Company B.V.'
                        legal_entity_status:
                          type: string
                          example: ACTIVE
                        legal_form:
                          type: string
                          example: 'Besloten Vennootschap'
                        legal_address_country:
                          type: string
                          example: NL
                        legal_address_city:
                          type: string
                          example: Amsterdam
                        legal_address_postal_code:
                          type: string
                          example: 1012AB
                        registration_authority_entity_id:
                          type: string
                          example: '12345678'
                        entity_creation_date:
                          type: string
                          example: '2020-01-15'
                        last_public_update_date:
                          type: string
                          example: '2023-11-20T10:30:00Z'
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                        example: 'http://example.com/api/lei?page=1'
                      last:
                        type: string
                        example: 'http://example.com/api/lei?page=5'
                      prev:
                        type: string
                        example: null
                      next:
                        type: string
                        example: 'http://example.com/api/lei?page=2'
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                        example: 1
                      per_page:
                        type: integer
                        example: 15
                      total:
                        type: integer
                        example: 73
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Invalid API key'
                properties:
                  message:
                    type: string
                    example: 'Invalid API key'
      tags:
        - 'Legal Entity Identifier (LEI)'
      security: []
  '/api/lei/{id}':
    get:
      summary: 'Get LEI entity by code'
      operationId: getLEIEntityByCode
      description: 'Retrieve a specific LEI entity using its LEI code.'
      parameters: []
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    lei: 724500VKKSH9QOLTFR81
                    legal_name: 'Example Company B.V.'
                    legal_entity_status: ACTIVE
                    legal_form: 'Besloten Vennootschap'
                    legal_address_country: NL
                    legal_address_city: Amsterdam
                    legal_address_postal_code: 1012AB
                    registration_authority_entity_id: '12345678'
                    entity_creation_date: '2020-01-15'
                    last_public_update_date: '2023-11-20T10:30:00Z'
                properties:
                  data:
                    type: object
                    properties:
                      lei:
                        type: string
                        example: 724500VKKSH9QOLTFR81
                      legal_name:
                        type: string
                        example: 'Example Company B.V.'
                      legal_entity_status:
                        type: string
                        example: ACTIVE
                      legal_form:
                        type: string
                        example: 'Besloten Vennootschap'
                      legal_address_country:
                        type: string
                        example: NL
                      legal_address_city:
                        type: string
                        example: Amsterdam
                      legal_address_postal_code:
                        type: string
                        example: 1012AB
                      registration_authority_entity_id:
                        type: string
                        example: '12345678'
                      entity_creation_date:
                        type: string
                        example: '2020-01-15'
                      last_public_update_date:
                        type: string
                        example: '2023-11-20T10:30:00Z'
        401:
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Invalid API key'
                properties:
                  message:
                    type: string
                    example: 'Invalid API key'
        404:
          description: 'Not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'No query results for model [App\Models\LeiEntity].'
                properties:
                  message:
                    type: string
                    example: 'No query results for model [App\Models\LeiEntity].'
      tags:
        - 'Legal Entity Identifier (LEI)'
      security: []
    parameters:
      -
        in: path
        name: id
        description: 'The ID of the lei.'
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: lei
        description: 'The LEI code (20 alphanumeric characters).'
        example: 724500VKKSH9QOLTFR81
        required: true
        schema:
          type: string
