OpenMercantil User API

Authenticated Panel Pro endpoints — segments, lists, notes, tags, exports, audit. Requires session cookie (browser) and X-CSRF-Token header for mutations.

OpenAPI Specification

openmercantil-user-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: OpenMercantil User API
  version: 1.9.3
  summary: Versioned public-read, browser-account, billing, support and provider-callback contracts.
  description: 'Public JSON API for Spanish company information derived from BORME and other public sources.
    OpenMercantil is an independent informational service; it is NOT the BOE, BORME or Registro Mercantil
    and does NOT replace official certificates or registry extracts.


    **Rate limits.** Free: 60 req/min y 200 req/día por IP. Planes superiores (Profesional 5.000 req/día,
    MAX 50.000 req/día, Enterprise 500.000+ req/día) según cuenta y API key. Cabeceras `X-RateLimit-Limit`,
    `X-RateLimit-Remaining`, `X-RateLimit-Reset`, `X-OpenMercantil-Plan`, `Retry-After`.


    **License and attribution.** Source-specific metadata in each response and the active versioned source
    catalog prevails. OpenMercantil does not relicense upstream content under a blanket license. Unknown,
    review and restricted datasets are omitted or return `503 legal_layer_unavailable`. BOE/BORME material
    is re-used under Ley 37/2007 and its official version remains boe.es. Court judgments are not exposed;
    CENDOJ remains citation-index only under CGPJ Reglamento 3/2010.


    **Machine-readable catalog (DCAT-AP-ES):** https://openmercantil.es/catalog.rdf'
  termsOfService: https://openmercantil.es/terminos-de-uso
  contact:
    name: OpenMercantil
    url: https://openmercantil.es/soporte
    email: social@openmercantil.es
  license:
    name: Source-specific upstream terms; see response catalog metadata
    url: https://openmercantil.es/terminos-de-uso
  x-publisher:
    name: OpenMercantil
    url: https://openmercantil.es/
    email: social@openmercantil.es
  x-spatial: http://publications.europa.eu/resource/authority/country/ESP
  x-temporal: 2009-01-01/..
  x-language: es
  x-dcat-catalog: https://openmercantil.es/catalog.rdf
  x-rate-limit:
    free:
      per_min: 60
      per_day: 200
      kind: anonymous-ip
    profesional:
      per_min: 120
      per_day: 5000
      kind: api-key
    max:
      per_min: 600
      per_day: 50000
      kind: api-key
    enterprise:
      per_min: 1200
      per_day: 500000
      kind: contract
  x-methodology: https://openmercantil.es/metodologia
  x-sources: https://openmercantil.es/fuentes
  x-corrections: https://openmercantil.es/correcciones
  x-contract-status: Public read, browser-account and provider-callback surfaces are explicitly separated
    in this contract. Operator/admin routes are excluded. The public MCP consumes only the allowlisted
    GET read plane.
  x-account-segment-contract:
    projection: company_public_v2 immutable corporate sidecar
    synchronous_row_cap: 500
    bounded_count_cap: 50001
    count_semantics: The segment run response count is the number of rows returned, never a global total.
      Dataset preview uses total_is_lower_bound=true and total_lower_bound when the bounded count reaches
      50001.
    related_web_dataset_surface:
      preview_path: /mi-cuenta/datasets/preview
      export_path: /mi-cuenta/datasets/export.csv
      synchronous_export_max_rows: 500
      overflow_status: 503
      overflow_error: async_export_required
  x-company-identity-contract:
    version: '1.0'
    projection: company_public_v2 immutable generation-bound corporate sidecar
    applies_to: Every /api/v1/company/{slug}*, /api/v1/empresa/{slug}* and /api/v1/grafo/{slug} read before
      any report, cache, graph or dataset lookup. /api/v1/companies/compare resolves both requested subjects
      in one bounded company_public_v2 batch before either row is exposed; MCP company tools inherit these
      preflights through REST.
    resolution:
      published: canonical corporate slug admitted
      safe_alias: internally canonicalized and Content-Location emitted
      withheld: neutral 404; includes absent, personal and ambiguous/quarantined identities
      unavailable: 503 with no-store; clients must not infer absence
    search: Exact corporate CIF, exact canonical/safe-alias slug, or bounded name_prefix2 pool scored
      in application code. DNI/NIE and ambiguous CIFs return zero items.
    public_company_count: company_public_projection_state.row_count
servers:
- url: https://openmercantil.es
  description: Production
tags:
- name: User
  description: Authenticated Panel Pro endpoints — segments, lists, notes, tags, exports, audit. Requires
    session cookie (browser) and X-CSRF-Token header for mutations.
paths:
  /api/v1/user/me:
    get:
      operationId: getUserMe
      tags:
      - User
      summary: Current authenticated user
      description: Returns id, email, name, plan (tier), persona_primary, onboarded flag and a fresh CSRF
        token. Requires active session cookie.
      security:
      - cookieAuth: []
      responses:
        '200':
          description: User profile
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserMeResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /api/v1/user/org:
    get:
      operationId: getUserOrganization
      tags:
      - User
      summary: Get the current organization, seats and visible members
      description: Returns null organization plus can_team when the user has no team. Non-privileged members
        receive masked peer email addresses; the caller's own email is never masked. Invitation tokens
        are never returned.
      x-plane: account
      security:
      - cookieAuth: []
      responses:
        '200':
          description: Organization context
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserOrganizationResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '503':
          description: Organization service unavailable
    post:
      operationId: createUserOrganization
      tags:
      - User
      summary: Create an organization
      description: MAX/Enterprise account mutation. The authenticated user becomes owner.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserOrganizationNameRequest'
      responses:
        '201':
          description: Organization created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrganizationCreatedResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          description: Plan does not include teams
        '403':
          description: Invalid CSRF
        '409':
          description: User already belongs to an organization
        '503':
          description: Organization service unavailable
    put:
      operationId: updateUserOrganization
      tags:
      - User
      summary: Rename the current organization
      description: Owner-only account mutation.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserOrganizationNameRequest'
      responses:
        '200':
          description: Organization renamed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Owner permission or CSRF required
        '404':
          $ref: '#/components/responses/NotFound'
        '503':
          description: Organization service unavailable
  /api/v1/user/org/invites:
    post:
      operationId: createUserOrganizationInvite
      tags:
      - User
      summary: Create or renew an organization invitation
      description: Owner/admin mutation. Enforces seat and daily invitation limits, sends the invitation
        out of band and never returns its token.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserOrganizationInviteRequest'
      responses:
        '201':
          description: Invitation created or renewed without token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrganizationInviteCreatedResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Owner/admin permission or CSRF required
        '409':
          description: No organization, duplicate member or no free seat
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          description: Organization or email service unavailable
  /api/v1/user/org/invites/{id}/resend:
    post:
      operationId: resendUserOrganizationInvite
      tags:
      - User
      summary: Rotate and resend an organization invitation
      description: Owner/admin mutation with no request body. The rotated token is sent out of band and
        never returned.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      responses:
        '200':
          description: Invitation resent
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmailDispatchResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Owner/admin permission or CSRF required
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: No free seat for an expired invitation
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          description: Organization or email service unavailable
  /api/v1/user/org/invites/{id}:
    delete:
      operationId: deleteUserOrganizationInvite
      tags:
      - User
      summary: Cancel a pending organization invitation
      description: Owner/admin mutation with no request body.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      responses:
        '200':
          description: Invitation cancelled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Owner/admin permission or CSRF required
        '404':
          $ref: '#/components/responses/NotFound'
        '503':
          description: Organization service unavailable
  /api/v1/user/org/members/{id}:
    put:
      operationId: updateUserOrganizationMember
      tags:
      - User
      summary: Change an organization member role
      description: Owner-only mutation; the owner and caller's own role cannot be changed.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserOrganizationMemberRoleRequest'
      responses:
        '200':
          description: Role updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Owner permission or CSRF required
        '404':
          $ref: '#/components/responses/NotFound'
        '503':
          description: Organization service unavailable
    delete:
      operationId: deleteUserOrganizationMember
      tags:
      - User
      summary: Remove a member from the organization
      description: Owner/admin mutation with no request body. Admins may remove members but not owners
        or other admins.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      responses:
        '200':
          description: Member removed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Owner/admin permission or CSRF required
        '404':
          $ref: '#/components/responses/NotFound'
        '503':
          description: Organization service unavailable
  /api/v1/user/org/leave:
    post:
      operationId: leaveUserOrganization
      tags:
      - User
      summary: Leave the current organization
      description: Member/admin mutation with no request body. Owners must transfer ownership through
        the supported process before leaving.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - $ref: '#/components/parameters/CsrfHeader'
      responses:
        '200':
          description: Organization left
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Owner cannot leave before transferring ownership
        '503':
          description: Organization service unavailable
  /api/v1/user/persona:
    get:
      operationId: getUserPersona
      tags:
      - User
      summary: Current persona config + available list
      security:
      - cookieAuth: []
      responses:
        '200':
          description: Persona config
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserPersonaResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
    post:
      operationId: postUserPersona
      tags:
      - User
      summary: Set persona_primary
      description: Set the account persona to a slug returned by the GET operation.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserPersonaUpdateRequest'
      responses:
        '200':
          description: Updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserPersonaSelectedResponse'
        '400':
          description: Invalid persona slug
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
  /api/v1/user/segments:
    get:
      operationId: getUserSegments
      x-query-contract:
        allowed:
        - pinned
        - limit
        unknown: 400 invalid_parameter
        non_scalar: 400 invalid_parameter
        lexical: 400 invalid_parameter
        range: 422 validation_failed
      tags:
      - User
      summary: List user segments
      parameters:
      - name: pinned
        in: query
        schema:
          type: string
          enum:
          - '0'
          - '1'
      - name: limit
        in: query
        schema:
          type: integer
          minimum: 1
          maximum: 500
          default: 200
      security:
      - cookieAuth: []
      responses:
        '200':
          description: Segments list with tier_max
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSegmentListResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '401':
          $ref: '#/components/responses/Unauthorized'
    post:
      operationId: postUserSegments
      tags:
      - User
      summary: Create segment
      description: Create a tier-limited saved corporate segment. At least one effective UserSegmentFilters
        anchor is required. Unknown fields and legacy forma/estado filters are rejected with 400; an individually
        valid but unindexed combination is rejected with 422.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserSegmentCreateRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSegmentCreatedResponse'
        '400':
          description: Malformed/unknown filter, legally unavailable legacy filter, missing effective
            anchor or tier limit
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Individually valid filters do not have a safe indexed combination
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /api/v1/user/segments/{id}:
    get:
      operationId: getUserSegmentsById
      tags:
      - User
      summary: Get segment
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: Segment
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSegment'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      operationId: putUserSegmentsById
      tags:
      - User
      summary: Replace mutable segment fields
      description: When filters_json is present it follows UserSegmentFilters. Invalid or legacy fields
        return 400; unsupported indexed combinations return 422.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserSegmentUpdateRequest'
      responses:
        '200':
          description: Updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '400':
          description: Malformed/unknown or legally unavailable filter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Individually valid filters do not have a safe indexed combination
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: patchUserSegmentsById
      tags:
      - User
      summary: Patch mutable segment fields
      description: When filters_json is present it follows UserSegmentFilters. Invalid or legacy fields
        return 400; unsupported indexed combinations return 422.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserSegmentUpdateRequest'
      responses:
        '200':
          description: Updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '400':
          description: Malformed/unknown or legally unavailable filter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Individually valid filters do not have a safe indexed combination
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteUserSegmentsById
      tags:
      - User
      summary: Delete segment
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      responses:
        '200':
          description: Deleted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
  /api/v1/user/segments/{id}/pin:
    post:
      operationId: postUserSegmentsByIdPin
      tags:
      - User
      summary: Toggle pin
      description: This mutation has no request body.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      responses:
        '200':
          description: New pinned state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSegmentPinResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
        '404':
          $ref: '#/components/responses/NotFound'
  /api/v1/user/segments/{id}/run:
    post:
      operationId: postUserSegmentsByIdRun
      x-query-contract:
        allowed:
        - limit
        unknown: 400 invalid_parameter
        non_scalar: 400 invalid_parameter
        lexical: 400 invalid_parameter
        range: 422 validation_failed
      tags:
      - User
      summary: Execute segment filters → companies
      description: Resolves filters_json only against the immutable corporate company_public_v2 sidecar
        and returns at most 500 rows. `count` is the number of rows in this bounded response, not an exact
        global total. Invalid/legacy filters return 400, unsupported indexed combinations return 422,
        and missing authority/sidecar or query failure returns 503. This mutation has no request body.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - name: limit
        in: query
        schema:
          type: integer
          minimum: 1
          default: 100
          maximum: 500
      - $ref: '#/components/parameters/CsrfHeader'
      responses:
        '200':
          description: Bounded result rows; count equals rows.length and is not a global total
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSegmentRunResponse'
        '400':
          description: Malformed/unknown or legally unavailable saved filter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Saved filters are valid individually but lack a safe indexed combination
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
        '404':
          $ref: '#/components/responses/NotFound'
        '503':
          description: Canonical authority, legal layer, immutable company sidecar or bounded query unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/user/lists:
    get:
      operationId: getUserLists
      tags:
      - User
      summary: List user lists
      security:
      - cookieAuth: []
      responses:
        '200':
          description: Lists with tier_max
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserListListResponse'
    post:
      operationId: postUserLists
      tags:
      - User
      summary: Create list
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserListCreateRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserListCreatedResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
  /api/v1/user/lists/{id}:
    get:
      operationId: getUserListsById
      tags:
      - User
      summary: Get list + items
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: List + items
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserListDetail'
    put:
      operationId: putUserListsById
      tags:
      - User
      summary: Replace mutable list fields
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserListUpdateRequest'
      responses:
        '200':
          description: Updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: patchUserListsById
      tags:
      - User
      summary: Patch mutable list fields
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserListUpdateRequest'
      responses:
        '200':
          description: Updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      operationId: deleteUserListsById
      tags:
      - User
      summary: Delete list and its items
      description: This mutation has no request body.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      responses:
        '200':
          description: Deleted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
  /api/v1/user/lists/{id}/items:
    post:
      operationId: postUserListsByIdItems
      tags:
      - User
      summary: Add item to list
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserListItemCreateRequest'
      responses:
        '201':
          description: Added
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
        '404':
          $ref: '#/components/responses/NotFound'
  /api/v1/user/lists/{id}/items/{item_id}:
    delete:
      operationId: deleteUserListsByIdItemsByItemId
      tags:
      - User
      summary: Remove item from list
      description: This mutation has no request body.
      x-plane: account
      security:
      - cookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - name: item_id
        in: path
        required: true
        schema:
          type: integer
          minimum: 1
      - $ref: '#/components/parameters/CsrfHeader'
      responses:
        '200':
          description: Removed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OkResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Invalid CSRF
        '404':
          $ref: '#/components/responses/NotFound'
  /api/v1/user/notes:
    get:
      operationId: getUserNotes
      x-query-contract:
        allowed:
        - limit
        unknown: 400 invalid_p

# --- truncated at 32 KB (130 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/openmercantil/refs/heads/main/openapi/openmercantil-user-api-openapi.yml