> ## 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.

# Update a scoring

> Replaces all candidatures and members and re-evaluates them synchronously.

The body contains only `candidatures`. `postalCode` and `monthlyPaymentAmountInEuros` stay fixed at creation; create a new scoring to change them.

Optional fields, income shapes and confidence rules are the same as creation. Omit `workingStatus` when it is unknown; explicit `null` is equivalent. Because PUT replaces all candidatures and members, omission clears any previously declared working status instead of preserving it. Send the complete current declaration for every member you want to keep.

**Response.** `204` with no body. Call `GET` to read the updated results.

**Retries.** Repeating the same request retries delinquency checks that failed with `service-unavailable`. Unchanged people reuse cached results.

**Errors.**
- `400` — invalid shape, types or scoring identifiers.
- `422` — invalid domain values or limits (same codes as creation).
- `404` — the scoring does not exist or belongs to another client.




## OpenAPI

````yaml /openapi/arco-partner-api.json put /scorings/{scoringId}
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:
  /scorings/{scoringId}:
    parameters:
      - $ref: '#/components/parameters/ScoringId'
    put:
      tags:
        - Scorings
      summary: Update a scoring
      description: >
        Replaces all candidatures and members and re-evaluates them
        synchronously.


        The body contains only `candidatures`. `postalCode` and
        `monthlyPaymentAmountInEuros` stay fixed at creation; create a new
        scoring to change them.


        Optional fields, income shapes and confidence rules are the same as
        creation. Omit `workingStatus` when it is unknown; explicit `null` is
        equivalent. Because PUT replaces all candidatures and members, omission
        clears any previously declared working status instead of preserving it.
        Send the complete current declaration for every member you want to keep.


        **Response.** `204` with no body. Call `GET` to read the updated
        results.


        **Retries.** Repeating the same request retries delinquency checks that
        failed with `service-unavailable`. Unchanged people reuse cached
        results.


        **Errors.**

        - `400` — invalid shape, types or scoring identifiers.

        - `422` — invalid domain values or limits (same codes as creation).

        - `404` — the scoring does not exist or belongs to another client.
      operationId: updateScoring
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateScoringRequest'
            examples:
              updateScoring:
                $ref: '#/components/examples/UpdateScoringRequest'
      responses:
        '204':
          description: Scoring updated and re-evaluated.
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '422':
          $ref: '#/components/responses/UnprocessableEntityError'
        '429':
          $ref: '#/components/responses/TooManyRequestsError'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  parameters:
    ScoringId:
      name: scoringId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Scoring identifier provided at creation.
  schemas:
    UpdateScoringRequest:
      type: object
      required:
        - candidatures
      properties:
        candidatures:
          type: array
          minItems: 1
          maxItems: 20
          description: Full replacement of candidatures and members.
          items: e500cd92-db39-4db6-bb54-4b3297a7a2bc
    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.
  examples:
    UpdateScoringRequest:
      summary: Replace candidatures
      value:
        candidatures:
          - externalReference: cand-001
            members:
              - personalId: 12345678Z
                workingStatus: employed
                netAnnualIncomeAmountInEuros: 25200
          - externalReference: cand-003
            members:
              - personalId: Y7654321G
                workingStatus: employed
                netAnnualIncomeAmountInEuros: 31000
  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
    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
  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.