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

# Issue the policy

> Requests the policy for a `ready-to-issue` case (Emisión), with the landlord's details and the direct-debit account. The insured property is the one sent when quoting.

When the offer is conditioned, Vivara first merges every uploaded document into a single PDF and sends it to the insurer, then requests the issuance. An offer that is not conditioned is issued without sending documents.
If any required document is missing, nothing is sent and the call fails with `422 documentation-incomplete`, listing what is missing.

Issuance can complete immediately (`policy-issued`, with the policy documents) or stay in `policy-requested` while the insurer finishes it
(for example, reviewing a conditioned offer or waiting for the landlord's electronic signature). In that case, poll `GET /cases/{caseId}`.

Safe to retry: if the case is already `policy-requested` or `policy-issued`, the case is returned as it is and nothing is sent to the insurer again.




## OpenAPI

````yaml /openapi/arco-partner-api.json post /non-payment-insurance/cases/{caseId}/policy
openapi: 3.1.0
info:
  title: Vivara Partner API
  version: 1.0.0
  description: >
    Vivara's external API for tenant scoring and non-payment insurance.


    ## Authentication


    Every request must include the `X-API-Key` header with the API key issued to
    the integration. Keys are scoped per API client: scorings and cases created
    with one key are not visible to other clients.


    ## Conventions


    - Money is always a number in euros with up to two decimals (`1250.5` =
    1,250.50 €).

    - Dates are `YYYY-MM-DD`; timestamps are ISO 8601 in UTC.

    - Every answer that carries a resource wraps it in `data`.

    - Every error has the same body: `status`, `statusCode`, `code` and
    `message`. Use `code`, which is stable, to decide what to do. The catalog of
    codes is in the guides.


    ## Processing model


    **Scorings.** Creating or updating a scoring evaluates every candidature
    synchronously and returns no body. Read the results with `GET
    /scorings/{scoringId}`.


    In this release, evaluation finishes during create or update and `status` is
    `completed`. Document upload and asynchronous evaluation will arrive in a
    later release (`processing` and candidature status `pending`).


    **Non-payment insurance.** You generate the id of the case (a UUID v4) and
    open it with `POST /non-payment-insurance/cases`, which prices the offer
    synchronously and answers `201` with a `Location` header and no body. A case
    id that was already used answers `409`, whatever the data. Read the case,
    with its offer and the documents it requires, with `GET
    /non-payment-insurance/cases/{caseId}`. Upload the documents, issue the
    policy with `POST /non-payment-insurance/cases/{caseId}/policy`, and poll
    the case with exponential backoff (at least 30 s between calls) until it is
    `policy-issued` or `rejected`.


    ## Edge, routing and rate limiting


    Traffic is served through Azure Front Door, which terminates TLS at
    `https://api.vivara.io/v1/*` and forwards requests to the partner API.

    The Front Door web application firewall enforces rate limits per client IP.
    When a limit is exceeded it returns `429 Too Many Requests`; requests
    blocked by firewall rules return `403 Forbidden`. Those two answers come
    from the firewall and have no `code`. A `403` with `code: forbidden` comes
    from the API, when the API client has no access to it. Rate limit values are
    shared during onboarding.


    ## Data protection


    Requests contain personal data (DNI or NIE, income, and the documents of the
    people on a rental contract). Delete a scoring with `DELETE
    /scorings/{scoringId}` once it is no longer needed. Remove a document
    uploaded by mistake with `DELETE
    /non-payment-insurance/cases/{caseId}/documents/{documentId}` while the case
    is `pending-documentation` or `ready-to-issue`. Cases cannot be deleted.
servers:
  - url: https://api.vivara.io/v1
    description: Production
  - url: https://api-stg.vivara.io/v1
    description: Staging
security:
  - apiKeyAuth: []
tags:
  - name: Scorings
    description: >-
      Score candidates for a property and prioritize who to offer a visit to
      first
  - name: Non-payment insurance
    description: >-
      Quote, document upload and policy issuance for rental non-payment
      insurance cases
paths:
  /non-payment-insurance/cases/{caseId}/policy:
    post:
      tags:
        - Non-payment insurance
      summary: Issue the policy
      description: >
        Requests the policy for a `ready-to-issue` case (Emisión), with the
        landlord's details and the direct-debit account. The insured property is
        the one sent when quoting.


        When the offer is conditioned, Vivara first merges every uploaded
        document into a single PDF and sends it to the insurer, then requests
        the issuance. An offer that is not conditioned is issued without sending
        documents.

        If any required document is missing, nothing is sent and the call fails
        with `422 documentation-incomplete`, listing what is missing.


        Issuance can complete immediately (`policy-issued`, with the policy
        documents) or stay in `policy-requested` while the insurer finishes it

        (for example, reviewing a conditioned offer or waiting for the
        landlord's electronic signature). In that case, poll `GET
        /cases/{caseId}`.


        Safe to retry: if the case is already `policy-requested` or
        `policy-issued`, the case is returned as it is and nothing is sent to
        the insurer again.
      operationId: issuePolicy
      parameters:
        - $ref: '#/components/parameters/CaseId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IssuePolicyRequest'
            examples:
              issuePolicy:
                $ref: '#/components/examples/IssuePolicyRequest'
      responses:
        '202':
          description: Issuance requested
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CaseResponse'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '409':
          $ref: '#/components/responses/ConflictError'
        '422':
          $ref: '#/components/responses/UnprocessableEntityError'
        '429':
          $ref: '#/components/responses/TooManyRequestsError'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '502':
          $ref: '#/components/responses/InsurerUnavailable'
components:
  parameters:
    CaseId:
      name: caseId
      in: path
      required: true
      description: The case id, a UUID v4 you generate before quoting.
      schema:
        type: string
        format: uuid
        example: 3f9c2a7e-58b1-4d0a-9a51-0c6e2f1b7d42
  schemas:
    IssuePolicyRequest:
      type: object
      description: The data needed to request the issuance of the policy.
      required:
        - landlord
        - correspondenceAddress
        - iban
        - consents
      properties:
        landlord:
          $ref: '#/components/schemas/LandlordDetails'
        correspondenceAddress:
          $ref: '#/components/schemas/Address'
        iban:
          type: string
          description: Spanish IBAN of the account the premium is direct-debited from.
          example: ES9121000418450200051332
        consents:
          $ref: '#/components/schemas/Consents'
    CaseResponse:
      type: object
      description: The case, wrapped in `data`.
      required:
        - data
      properties:
        data:
          $ref: '#/components/schemas/Case'
    LandlordDetails:
      description: >-
        Contact details of the landlord. The shape depends on `type`, which must
        match the landlord's document: `company` for a CIF and `individual` for
        any other.
      oneOf:
        - $ref: '#/components/schemas/IndividualLandlord'
        - $ref: '#/components/schemas/CompanyLandlord'
      discriminator:
        propertyName: type
        mapping:
          individual: '#/components/schemas/IndividualLandlord'
          company: '#/components/schemas/CompanyLandlord'
    Address:
      type: object
      description: A postal address in Spain.
      required:
        - streetType
        - street
        - postalCode
        - city
        - province
      properties:
        streetType:
          $ref: '#/components/schemas/StreetType'
        street:
          type: string
          description: Street name without its type ("Velázquez", not "Calle Velázquez").
          example: Velázquez
        number:
          type: integer
          description: Omit it when the street has no number.
          example: 42
        floor:
          type: string
          description: Floor of the building.
          example: '3'
        door:
          type: string
          description: Door of the floor.
          example: B
        postalCode:
          type: string
          description: Five-digit postal code.
          pattern: ^\d{5}$
          example: '28001'
        city:
          type: string
          description: City or town.
          example: Madrid
        province:
          type: string
          description: Province.
          example: Madrid
    Consents:
      type: object
      description: The consents the landlord gives when the policy is issued.
      required:
        - privacyPolicyAccepted
        - agreesToBeContacted
      properties:
        privacyPolicyAccepted:
          type: boolean
          description: The landlord accepted the insurer's privacy policy. Must be `true`.
          example: true
        agreesToBeContacted:
          type: boolean
          description: >-
            The landlord agrees to be contacted by the insurer for commercial
            purposes.
          example: false
    Case:
      type: object
      description: A rental contract being insured, from its quote to the issued policy.
      required:
        - id
        - status
        - effectiveDate
        - contractDurationMonths
        - rentalAmountInEuros
        - tenants
        - documentation
        - allowedActions
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          description: The case id you generated when asking for the quote.
          format: uuid
          example: 3f9c2a7e-58b1-4d0a-9a51-0c6e2f1b7d42
        externalReference:
          type: string
          description: Your own identifier for the rental contract, as sent in the quote.
          example: CONTRACT-2026-004521
        status:
          $ref: '#/components/schemas/CaseStatus'
        statusReason:
          type: string
          description: Human-readable explanation of the current status, in Spanish.
          example: Faltan 3 documentos para poder emitir la póliza.
        effectiveDate:
          type: string
          description: Start date of the policy, `YYYY-MM-DD`.
          format: date
          example: '2026-11-01'
        contractDurationMonths:
          type: integer
          description: Duration of the rental contract covered by the policy, in months.
          example: 12
        rentalAmountInEuros:
          type: number
          description: Monthly rental amount in euros (rent plus monthly expenses).
          example: 1250
        tenants:
          type: array
          description: Every person on the rental contract.
          items:
            $ref: '#/components/schemas/CaseTenant'
        offer:
          $ref: '#/components/schemas/Offer'
        documentation:
          $ref: '#/components/schemas/Documentation'
        policy:
          $ref: '#/components/schemas/Policy'
        allowedActions:
          type: array
          description: What you can do with the case right now.
          items:
            $ref: '#/components/schemas/CaseAction'
          example:
            - upload-document
        createdAt:
          type: string
          description: When the case was opened.
          format: date-time
          example: '2026-10-26T09:14:03Z'
        updatedAt:
          type: string
          description: When the case last changed.
          format: date-time
          example: '2026-10-26T09:14:05Z'
    Error:
      type: object
      required:
        - status
        - statusCode
        - code
        - message
      properties:
        status:
          type: string
          description: HTTP reason phrase.
        statusCode:
          type: integer
          description: HTTP status code.
        code:
          type: string
          description: >-
            Stable, machine-readable error code in kebab-case. Use it, not the
            message, to decide what to do. The full list is in the error catalog
            of the guides (Key concepts, Errors).
        message:
          type: string
          description: >-
            Human-readable explanation, in English. It names the fields or the
            documents behind the error.
    IndividualLandlord:
      type: object
      description: Contact details of a landlord that is an individual.
      required:
        - type
        - firstName
        - lastName
        - birthDate
        - sex
        - email
        - phone
      properties:
        type:
          type: string
          description: Always `individual`.
          enum:
            - individual
          example: individual
        firstName:
          type: string
          description: First name.
          example: Lucía
        lastName:
          type: string
          description: Last name.
          example: Fernández Ruiz
        birthDate:
          type: string
          description: Date of birth, `YYYY-MM-DD`.
          format: date
          example: '1978-02-23'
        sex:
          type: string
          description: Sex of the landlord.
          enum:
            - female
            - male
          example: female
        email:
          type: string
          description: Contact email.
          format: email
          example: lucia.fernandez@example.com
        phone:
          type: string
          pattern: ^\d{9}$
          description: Spanish phone number, 9 digits.
          example: '612345678'
    CompanyLandlord:
      type: object
      description: Contact details of a landlord that is a company.
      required:
        - type
        - legalName
        - email
        - phone
      properties:
        type:
          type: string
          description: Always `company`.
          enum:
            - company
          example: company
        legalName:
          type: string
          description: Legal name of the company.
          example: Inversiones Castellana SL
        email:
          type: string
          description: Contact email.
          format: email
          example: admin@castellana.example.com
        phone:
          type: string
          description: Spanish phone number, 9 digits.
          pattern: ^\d{9}$
          example: '914567890'
    StreetType:
      type: string
      description: The type of street, as the insurer names it.
      enum:
        - street
        - avenue
        - square
        - promenade
        - road
        - way
        - path
        - passage
        - boulevard
        - roundabout
        - ring-road
        - tree-lined-avenue
        - transverse-road
        - cross-street
        - alley
        - slope
        - uphill
        - downhill
        - place
        - park
        - neighbourhood
        - colony
        - development
        - extension
        - group
        - block
        - city-block
        - building
        - tower
        - chalet
        - industrial-estate
        - plot
        - hamlet
        - settlement
        - village
        - stream
      example: street
    CaseStatus:
      type: string
      enum:
        - pending-documentation
        - ready-to-issue
        - rejected
        - policy-requested
        - policy-issued
        - failed
      description: >
        - `pending-documentation`: the offer is priced. Upload the documents in
        `documentation.missing`.

        - `ready-to-issue`: every required document is uploaded. You can issue
        the policy.

        - `rejected`: the insurer will not cover the contract. Final.

        - `policy-requested`: the documents and the issuance have been sent; the
        insurer is issuing the policy.

        - `policy-issued`: the policy is in force. Final.

        - `failed`: Vivara could not complete the last step with the insurer. It
        can appear from any status and it is not final: Vivara is notified and
        retries, and the case leaves it once the step completes. Keep polling;
        contact support if it persists.
      example: pending-documentation
    CaseTenant:
      type: object
      description: A person on the rental contract, with the id Vivara assigned.
      required:
        - id
        - role
        - personalId
      properties:
        id:
          type: string
          format: uuid
          description: Use it as `tenantId` when uploading this tenant's documents.
          example: 6b1e0d44-2c3f-4b8e-a0f2-91d7e5c3a810
        externalReference:
          type: string
          description: Your own identifier for this person, as sent in the quote.
          example: TENANT-88412
        role:
          $ref: '#/components/schemas/TenantRole'
        personalId:
          type: string
          description: >-
            Identification number of the person, as sent when the case was
            opened.
          example: X1234567L
    Offer:
      type: object
      description: The priced offer. Present once the insurer has answered.
      required:
        - code
        - description
        - contractable
        - coverages
        - exceptions
        - exclusions
      properties:
        code:
          type: integer
          description: Code of the offer at the insurer.
          example: 16
        description:
          type: string
          description: Name of the offer, in Spanish.
          example: Protección Jurídica Familiar - Impago de alquiler
        contractable:
          type: boolean
          description: Whether the offer can be issued as it stands.
          example: true
        netPremiumInEuros:
          type:
            - number
            - 'null'
          description: Annual premium before taxes, in euros.
          example: 423.5
        totalPremiumInEuros:
          type:
            - number
            - 'null'
          description: Annual premium including taxes.
          example: 451.2
        firstInstallmentInEuros:
          type:
            - number
            - 'null'
          description: Amount of the first installment, in euros.
          example: 451.2
        remainingInstallmentsInEuros:
          type:
            - number
            - 'null'
          description: Amount of each remaining installment, in euros.
          example: 0
        conditionsPdfUrl:
          type: string
          format: uri
          description: The insurer's offer document.
          example: https://files.vivara.es/npi/3f9c2a7e/offer.pdf
        coverages:
          type: array
          description: The coverages the offer includes.
          items:
            $ref: '#/components/schemas/Coverage'
        exceptions:
          type: array
          description: >-
            Reasons the offer is conditioned. The insurer reviews them against
            the documentation after the issuance request.
          items:
            $ref: '#/components/schemas/InsurerNotice'
        exclusions:
          type: array
          description: Reasons the offer cannot be contracted.
          items:
            $ref: '#/components/schemas/InsurerNotice'
    Documentation:
      type: object
      description: >-
        The documentation of the case: what is required, what is missing and
        what was uploaded.
      required:
        - complete
        - missing
        - documents
      properties:
        complete:
          type: boolean
          description: Every requirement is met, so the policy can be issued.
          example: false
        sentToInsurerAt:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            When the documents were merged and sent to the insurer, as part of
            the issuance. `null` until then.
          example: null
        missing:
          type: array
          description: Requirements still unmet. Empty once everything is uploaded.
          items:
            $ref: '#/components/schemas/DocumentRequirement'
        documents:
          type: array
          description: Documents uploaded so far.
          items:
            $ref: '#/components/schemas/UploadedDocument'
    Policy:
      type: object
      description: Present once issuance has been requested.
      required:
        - status
      properties:
        status:
          type: string
          enum:
            - pending-signature
            - pending-insurer
            - issued
          description: >
            - `pending-signature`: the landlord must sign the policy
            electronically (the insurer emails them).

            - `pending-insurer`: the insurer is finishing the issuance.

            - `issued`: the policy is in force.
          example: issued
        policyNumber:
          type: string
          description: The policy number, once the insurer assigns it.
          example: '0471203398'
        requestedAt:
          type: string
          description: When the issuance was requested.
          format: date-time
          example: '2026-10-26T11:30:00Z'
        issuedAt:
          type: string
          description: When the policy was issued.
          format: date-time
          example: '2026-10-26T11:30:04Z'
        documents:
          type: array
          description: Documents of the policy.
          items:
            $ref: '#/components/schemas/PolicyDocument'
    CaseAction:
      type: string
      description: An action the partner can take on the case in its current status.
      enum:
        - upload-document
        - issue-policy
    TenantRole:
      type: string
      description: Whether the person is a tenant or a guarantor.
      enum:
        - tenant
        - guarantor
      example: tenant
    Coverage:
      type: object
      description: A coverage included in the offer.
      required:
        - code
        - sumInsuredInEuros
      properties:
        code:
          type: integer
          description: Code of the coverage at the insurer.
          example: 101
        sumInsuredInEuros:
          type: number
          description: Maximum amount the coverage pays, in euros.
          example: 15000
    InsurerNotice:
      type: object
      description: A reason the insurer gives about the offer, with its own code.
      required:
        - code
        - description
      properties:
        code:
          type: string
          description: Code of the notice at the insurer.
          example: EX-214
        description:
          type: string
          description: What the insurer says, in Spanish.
          example: Ratio renta/ingresos superior al permitido
    DocumentRequirement:
      type: object
      description: A requirement the uploaded documents must still meet.
      required:
        - anyOf
        - minFiles
        - uploadedFiles
      properties:
        tenantId:
          type: string
          format: uuid
          description: The tenant the requirement is for. Absent for case requirements.
          example: 6b1e0d44-2c3f-4b8e-a0f2-91d7e5c3a810
        anyOf:
          type: array
          description: Any of these document types satisfies the requirement.
          items:
            $ref: '#/components/schemas/DocumentType'
          example:
            - employment-contract
            - work-history-report
        minFiles:
          type: integer
          description: How many files the requirement needs.
          example: 1
        uploadedFiles:
          type: integer
          description: How many files were uploaded for it so far.
          example: 0
        templateUrl:
          type: string
          format: uri
          description: >-
            A template to fill in and sign, when the document is one Vivara
            provides.
          example: https://files.vivara.es/npi/templates/anexo-lopd.pdf
    UploadedDocument:
      type: object
      required:
        - id
        - type
        - fileName
        - uploadedAt
      properties:
        id:
          type: string
          description: The document id. Use it to remove the document.
          format: uuid
          example: c41a8e93-7d2b-4f6a-b5e1-2a9f0c8d3e17
        type:
          $ref: '#/components/schemas/DocumentType'
        tenantId:
          type: string
          description: The tenant the document belongs to. Absent for case documents.
          format: uuid
          example: 6b1e0d44-2c3f-4b8e-a0f2-91d7e5c3a810
        fileName:
          type: string
          description: Name of the uploaded file.
          example: nomina-septiembre.pdf
        uploadedAt:
          type: string
          description: When the document was stored.
          format: date-time
          example: '2026-10-26T10:02:41Z'
    PolicyDocument:
      type: object
      description: A document of the issued policy.
      required:
        - type
        - url
      properties:
        type:
          type: string
          description: Kind of document.
          enum:
            - policy
            - certificate
            - direct-debit-mandate
          example: policy
        url:
          type: string
          description: Where to download it.
          format: uri
          example: https://files.vivara.es/npi/3f9c2a7e/policy.pdf
    DocumentType:
      type: string
      enum:
        - data-protection-consent
        - identity-document
        - employment-contract
        - work-history-report
        - payslip
        - income-tax-return
        - quarterly-tax-return
        - pension-certificate
        - company-tax-id-card
        - corporate-income-tax-return
        - power-of-attorney
        - guarantor-identity-document
        - guarantor-income-proof
        - military-commitment
      description: >
        `data-protection-consent` is the signed data protection annex (Anexo
        LOPD), a case document signed by the landlord and every tenant. Every
        other type is a tenant document.
      example: payslip
  examples:
    IssuePolicyRequest:
      summary: An individual landlord paying by direct debit
      value:
        landlord:
          type: individual
          firstName: Carmen
          lastName: Ruiz Soler
          birthDate: '1975-04-12'
          sex: female
          email: carmen.ruiz@example.com
          phone: '600123456'
        correspondenceAddress:
          streetType: avenue
          street: de América
          number: 45
          postalCode: '28028'
          city: Madrid
          province: Madrid
        iban: ES9121000418450200051332
        consents:
          privacyPolicyAccepted: true
          agreesToBeContacted: false
  responses:
    BadRequestError:
      description: >-
        Bad request. The body, path or headers do not match the expected shape
        or types.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            invalidScoring:
              summary: Invalid scoring
              value:
                status: Bad Request
                statusCode: 400
                code: validation-error
                message: >-
                  "candidatures[0].members[0].netAnnualIncomeAmountInEuros" must
                  be a number
            invalidQuote:
              summary: Invalid quote
              value:
                status: Bad Request
                statusCode: 400
                code: validation-error
                message: '"insuredProperty" is required'
    UnauthorizedError:
      description: >-
        Unauthorized. The X-API-Key header is missing or the API key is not
        valid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            status: Unauthorized
            statusCode: 401
            code: invalid-api-key
            message: Invalid API key
    ForbiddenError:
      description: >-
        Forbidden. The API client has no access to this API, or the request was
        blocked by the edge firewall.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/Error'
              - 179b90ba-7311-450d-aaec-7de48cb6a4fb
          examples:
            forbidden:
              summary: The API client has no access to this API
              value:
                status: Forbidden
                statusCode: 403
                code: forbidden
                message: The API client has no access to this API
            firewall:
              summary: Blocked by the edge firewall
              value:
                status: Forbidden
                statusCode: 403
                message: Request blocked by the firewall
    NotFoundError:
      description: >-
        Not found. The scoring, the case or the document does not exist for the
        authenticated API client.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            scoringNotFound:
              summary: Scoring not found
              value:
                status: Not Found
                statusCode: 404
                code: scoring-not-found
                message: Scoring 6d1f0c3e-5b8a-4c1e-9f2a-3b7e8d4a1c90 not found
            caseNotFound:
              summary: Case not found
              value:
                status: Not Found
                statusCode: 404
                code: case-not-found
                message: No case exists with id 3f9c2a7e-58b1-4d0a-9a51-0c6e2f1b7d42.
            documentNotFound:
              summary: Document not found in the case
              value:
                status: Not Found
                statusCode: 404
                code: document-not-found
                message: >-
                  No document exists with id
                  c41a8e93-7d2b-4f6a-b5e1-2a9f0c8d3e17 in case
                  3f9c2a7e-58b1-4d0a-9a51-0c6e2f1b7d42.
            pathNotFound:
              summary: The path does not exist
              value:
                status: Not Found
                statusCode: 404
                code: not-found
                message: Cannot GET /non-payment-insurance/unknown
    ConflictError:
      description: >-
        Conflict. The id is already in use with other data, or the status of the
        resource does not allow the operation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            scoringAlreadyExists:
              summary: Scoring id already in use
              value:
                status: Conflict
                statusCode: 409
                code: scoring-already-exists
                message: Scoring 6d1f0c3e-5b8a-4c1e-9f2a-3b7e8d4a1c90 already exists
            caseAlreadyExists:
              summary: Case id already used with different data
              value:
                status: Conflict
                statusCode: 409
                code: case-already-exists
                message: Case 3f9c2a7e-58b1-4d0a-9a51-0c6e2f1b7d42 already exists.
            invalidCaseStatus:
              summary: The case status does not allow the action
              value:
                status: Conflict
                statusCode: 409
                code: invalid-case-status
                message: >-
                  The policy can only be issued for a ready-to-issue case; this
                  case is rejected.
    UnprocessableEntityError:
      description: >
        Unprocessable entity. The body is well formed but breaks a business rule
        (such as a duplicated candidature externalReference, a duplicated
        personal id within the scoring, an invalid DNI or NIE, or a change of
        fields that are fixed at creation), or the case lacks documents the
        insurer requires.

        Product validation codes are `scoring-has-invalid-candidature-count`,
        `scoring-has-invalid-member-count`,
        `scoring-has-duplicated-candidature-reference` and
        `scoring-has-duplicated-member`. Other field validation errors may omit
        `code`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            duplicatedPersonalId:
              summary: Personal id repeated within the scoring
              value:
                status: Unprocessable Entity
                statusCode: 422
                code: scoring-has-duplicated-member
                message: personal id 12345678Z is duplicated in the scoring
            immutableFieldChanged:
              summary: Postal code changed on update
              value:
                status: Unprocessable Entity
                statusCode: 422
                code: immutable-field-changed
                message: Postal code cannot be changed after creation
            documentationIncomplete:
              summary: >-
                Documents missing when issuing the policy. Nothing was sent to
                the insurer
              value:
                status: Unprocessable Entity
                statusCode: 422
                code: documentation-incomplete
                message: >-
                  2 required documents are missing: tenant
                  6b1e0d44-2c3f-4b8e-a0f2-91d7e5c3a810 needs 2 of payslip (1
                  uploaded); case needs 1 of data-protection-consent (0
                  uploaded).
            ownerDataIncomplete:
              summary: The landlord data the insurer needs to issue is missing
              value:
                status: Unprocessable Entity
                statusCode: 422
                code: owner-data-incomplete
                message: >-
                  The insurer needs more data about the landlord: missing
                  owner.email, owner.address
            unreadableDocument:
              summary: A stored document cannot be read
              value:
                status: Unprocessable Entity
                statusCode: 422
                code: unreadable-document
                message: The document payslip.pdf cannot be read.
            documentationTooLarge:
              summary: The merged documentation is too large for the insurer
              value:
                status: Unprocessable Entity
                statusCode: 422
                code: documentation-too-large
                message: >-
                  The documents of the case are too large to send to the
                  insurer.
    TooManyRequestsError:
      description: >-
        Too many requests. The rate limit enforced by Azure Front Door was
        exceeded. Retry with exponential backoff.
      content:
        application/json:
          schema:
            type: object
            description: >-
              Error answered by the edge firewall (Azure Front Door), before the
              request reaches the API. It has no `code`.
            required:
              - status
              - statusCode
              - message
            properties:
              status:
                type: string
                description: HTTP reason phrase.
              statusCode:
                type: integer
                description: HTTP status code.
              message:
                type: string
                description: Human-readable explanation.
          example:
            status: Too Many Requests
            statusCode: 429
            message: Rate limit exceeded
    InternalServerError:
      description: Internal server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            status: Internal Server Error
            statusCode: 500
            code: internal-error
            message: Something went wrong
    InsurerUnavailable:
      description: The insurer did not answer. Safe to retry with the same case id.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            status: Bad Gateway
            statusCode: 502
            code: insurer-unavailable
            message: The insurer is temporarily unavailable. Retry in a few minutes.
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: API key issued per external API client.

````

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