> ## Documentation Index
> Fetch the complete documentation index at: https://docs.melso.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Melso MCP: https://mcp.melso.ai/mcp (OAuth; one company per connection). Documentation-search MCP: https://docs.melso.ai/mcp; it does not act on customer accounts.
>
> Use the live tool list and respect company membership. Ask the person to approve the exact invoice or tax return version in the signed-in app. Melso's professionals prepare and file included returns after approval; an AI assistant does not file. A prepared file or an approval is not evidence of filing: only the AEAT's reference and receipt are. Keep credentials out of chat and logs.

# Submit a payroll run

> Sends the payslips your platform calculated for one month.

<Info>
  **Preview.** A contract we are building with design partners. It is not callable yet, and fields can still change. See [Availability](/api/availability).
</Info>

Melso does not
recalculate the payslips. It validates them against each employee's
affiliation and contribution bases, then uses them for three things:

* the month's Social Security contribution settlement (liquidación
  directa) and its CRA data,
* the work-income boxes of the modelo 111, and the employee records
  (key A) of the year's modelo 190,
* each employee's annual withholding certificate.

Send a second run with `kind` `supplementary` for arrears or late
corrections of an earlier month.


## OpenAPI

````yaml api/openapi.yaml POST /companies/{company_id}/payroll-runs
openapi: 3.1.0
info:
  title: Melso API
  version: 1.0.0-preview
  summary: Spanish tax and labour compliance for the companies on your platform.
  description: |
    The Melso API lets an HR, payroll, banking or ERP platform run the
    Spanish tax and labour obligations of the companies it serves: invoices,
    books, tax returns, Social Security and employment notifications.

    Melso calculates and prepares. A person at the company approves the exact
    version. Melso's professionals file under the company's representation, and
    the filing is proven only by the administration's reference and receipt.

    Every operation states its availability in `x-melso-status`:

    - `live`: Melso runs this capability in production today. Partner keys
      reach it once a partner account is enabled.
    - `preview`: a contract proposed to design partners. Not callable yet.

    `x-melso-actor: person` marks a decision a signed-in person makes in
    Melso; a partner sends them the approval link instead.
  contact:
    name: Melso partnerships
    email: hello@melso.ai
    url: https://docs.melso.ai/api/overview
servers:
  - url: https://api.melso.ai/v1
    description: API. Keys and access are issued per partner.
security:
  - partnerKey: []
tags:
  - name: Companies
    description: The companies you operate for, their fiscal profile and hosted onboarding.
  - name: Mandates
    description: >-
      The company's representation of Melso before the AEAT, the TGSS and the
      SEPE.
  - name: Webhook endpoints
    description: Where Melso sends signed events about your companies.
  - name: Invoicing setup
    description: Registration of the company as a VERI*FACTU or TicketBAI invoice issuer.
  - name: Customers
    description: The company's invoice customers.
  - name: Invoices
    description: >-
      Drafts, approval, legal registration, delivery and payment of the
      company's invoices.
  - name: Expenses
    description: >-
      Purchase invoices and receipts, with their AEAT category and
      deductibility.
  - name: Income
    description: Income invoiced outside Melso.
  - name: Documents
    description: >-
      Files the company gives Melso, and Melso's structured reading of an
      invoice or receipt.
  - name: Banking
    description: >-
      Bank accounts, movements, statements and reconciliation with invoices and
      expenses.
  - name: Accounting
    description: Journal, imported books and the company's financial statements.
  - name: Tax calendar
    description: The forms the company must file, with their periods and deadlines.
  - name: Tax returns
    description: The returns Melso calculates, their approval and their filing.
  - name: Corporate tax
    description: The year's corporate tax (modelo 200) and its instalments (modelo 202).
  - name: Tax estimates
    description: What the company should set aside for taxes, as of today.
  - name: Cases
    description: Gestiones, the procedures Melso's professionals carry out for the company.
  - name: Administration notifications
    description: Electronic notifications from the administration to the company.
  - name: Certificates
    description: >-
      Official certificates such as being up to date with the AEAT or the Social
      Security.
  - name: Employees
    description: The people the company employs.
  - name: Payroll runs
    description: >-
      The payroll results your platform calculated, for Melso to settle and
      declare.
  - name: Social Security
    description: >-
      Affiliation (altas, bajas and variaciones) and monthly contribution
      settlements.
  - name: Employment notifications
    description: >-
      Contrat@ contract notifications and Certific@2 company certificates to the
      SEPE.
paths:
  /companies/{company_id}/payroll-runs:
    parameters:
      - $ref: '#/components/parameters/CompanyId'
    post:
      tags:
        - Payroll runs
      summary: Submit a payroll run
      description: >
        Sends the payslips your platform calculated for one month. Melso does
        not

        recalculate the payslips. It validates them against each employee's

        affiliation and contribution bases, then uses them for three things:


        - the month's Social Security contribution settlement (liquidación
          directa) and its CRA data,
        - the work-income boxes of the modelo 111, and the employee records
          (key A) of the year's modelo 190,
        - each employee's annual withholding certificate.


        Send a second run with `kind` `supplementary` for arrears or late

        corrections of an earlier month.
      operationId: createPayrollRun
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PayrollRunInput'
            example:
              period: 2026-10
              kind: ordinary
              payment_date: '2026-10-31'
              external_id: run_2026_10
              payslips:
                - employee_id: 6a1f0c2e-4b3d-4e5f-8a9b-0c1d2e3f4a5b
                  days_contributed: 31
                  gross_pay: '2450.00'
                  in_kind_pay: '0.00'
                  irpf:
                    base: '2450.00'
                    rate: '14.20'
                    withheld: '347.90'
                  social_security:
                    base_common_contingencies: '2654.17'
                    base_professional_contingencies: '2654.17'
                    employee_contribution: '172.79'
                  concepts:
                    - code: salario_base
                      description: Salario base
                      amount: '1900.00'
                      kind: salary
                    - code: plus_transporte
                      description: Plus transporte
                      amount: '150.00'
                      kind: non_salary
      responses:
        '201':
          description: >-
            The run, `received`. Validation results arrive in `issues` and with
            the `payroll_run.validated` event.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PayrollRun'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          $ref: '#/components/responses/Conflict'
components:
  parameters:
    CompanyId:
      name: company_id
      in: path
      required: true
      description: >-
        The company's ID. Every company-scoped call works in exactly this
        company.
      schema:
        type: string
        format: uuid
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      description: >-
        A unique key, such as a UUID, that makes a retried create safe. Reusing
        a key with a different body is refused.
      schema:
        type: string
        maxLength: 255
  schemas:
    PayrollRunInput:
      type: object
      required:
        - period
        - kind
        - payment_date
        - payslips
      additionalProperties: false
      properties:
        period:
          type: string
          pattern: ^[0-9]{4}-(0[1-9]|1[0-2])$
          description: The month the pay accrues to, such as `2026-10`.
        kind:
          type: string
          enum:
            - ordinary
            - extra
            - supplementary
          description: >-
            `extra` for a paga extraordinaria paid apart; `supplementary` for
            arrears or a correction of an earlier month.
        payment_date:
          type: string
          format: date
        external_id:
          type: string
          description: Your ID for the run.
        payslips:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/PayslipInput'
    PayrollRun:
      type: object
      required:
        - id
        - period
        - kind
        - status
        - created_at
      properties:
        id:
          type: string
          format: uuid
        period:
          type: string
        kind:
          type: string
          enum:
            - ordinary
            - extra
            - supplementary
        external_id:
          type:
            - string
            - 'null'
        status:
          type: string
          enum:
            - received
            - validated
            - rejected
            - settled
          description: >-
            `validated`: usable for the settlement and the returns. `rejected`:
            see `issues`. `settled`: the month's contribution settlement is
            confirmed.
        totals:
          type: object
          properties:
            employees:
              type: integer
            gross_pay:
              $ref: '#/components/schemas/Amount'
            irpf_withheld:
              $ref: '#/components/schemas/Amount'
            employee_contributions:
              $ref: '#/components/schemas/Amount'
        issues:
          type: array
          items:
            type: object
            properties:
              employee_id:
                type:
                  - string
                  - 'null'
                format: uuid
              code:
                type: string
                description: >-
                  Such as `not_affiliated`, `base_below_minimum`,
                  `base_above_maximum` or `days_exceed_affiliation`.
              message:
                type: string
              blocking:
                type: boolean
        settlement_id:
          type:
            - string
            - 'null'
          format: uuid
        tax_return_ids:
          type: array
          description: The 111 (and, in January, the 190) this run feeds.
          items:
            type: string
            format: uuid
        created_at:
          type: string
          format: date-time
    PayslipInput:
      type: object
      required:
        - employee_id
        - days_contributed
        - gross_pay
        - irpf
        - social_security
      additionalProperties: false
      properties:
        employee_id:
          type: string
          format: uuid
        days_contributed:
          type: integer
          minimum: 0
          maximum: 31
        gross_pay:
          $ref: '#/components/schemas/Amount'
          description: Cash pay before deductions (percepciones dinerarias).
        in_kind_pay:
          $ref: '#/components/schemas/Amount'
          description: Pay in kind at its tax value (retribuciones en especie).
        irpf:
          type: object
          required:
            - base
            - rate
            - withheld
          properties:
            base:
              $ref: '#/components/schemas/Amount'
            rate:
              $ref: '#/components/schemas/Decimal'
            withheld:
              $ref: '#/components/schemas/Amount'
              description: IRPF withheld on cash pay.
            payment_on_account:
              $ref: '#/components/schemas/Amount'
              description: Ingreso a cuenta on pay in kind.
        social_security:
          type: object
          required:
            - base_common_contingencies
            - base_professional_contingencies
            - employee_contribution
          properties:
            base_common_contingencies:
              $ref: '#/components/schemas/Amount'
            base_professional_contingencies:
              $ref: '#/components/schemas/Amount'
            overtime_base:
              $ref: '#/components/schemas/Amount'
            employee_contribution:
              $ref: '#/components/schemas/Amount'
              description: The employee's share you deducted.
        concepts:
          type: array
          description: >-
            The payslip's concepts, used for the CRA (comunicación de conceptos
            retributivos abonados).
          items:
            type: object
            required:
              - code
              - amount
              - kind
            properties:
              code:
                type: string
              description:
                type: string
              amount:
                $ref: '#/components/schemas/Amount'
              kind:
                type: string
                enum:
                  - salary
                  - non_salary
                  - in_kind
                  - severance
    Amount:
      type: string
      pattern: ^-?[0-9]+\.[0-9]{2}$
      description: >-
        An amount in euros as a decimal string with two decimals, such as
        `"121.00"`.
      examples:
        - '121.00'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          description: What went wrong, for a person to read.
        code:
          type: string
          description: >-
            A stable code to branch on, such as `invoicing_not_ready` or
            `version_conflict`.
        request_id:
          type: string
          description: Quote it when you contact Melso.
    Decimal:
      type: string
      pattern: ^-?[0-9]{1,10}(\.[0-9]{1,6})?$
      description: A decimal number as a string, such as `"21"` or `"0.5"`.
  responses:
    BadRequest:
      description: >-
        The request is malformed or a field is invalid. Unknown fields are
        refused.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: lines[0].vat_rate must be 21, 10, 4 or 0
            code: invalid_invoice
            request_id: req_01JAB3K9X2
    Unauthorized:
      description: The key is missing, revoked or invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: invalid token
            code: unauthorized
            request_id: req_01JAB3K9X2
    Forbidden:
      description: The key cannot do this in this company, or the step needs a person.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Review and approve in the authenticated web application
            code: person_required
            request_id: req_01JAB3K9X2
    Conflict:
      description: >-
        The object changed or is not in a state that allows this. Read it again
        and decide.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: The tax return changed or is not ready for approval
            code: version_conflict
            request_id: req_01JAB3K9X2
  securitySchemes:
    partnerKey:
      type: http
      scheme: bearer
      description: |
        Your partner secret key, `mk_live_…` for real companies or `mk_test_…`
        for test companies. Keep it on your servers. See
        [Authentication](/api/authentication).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.