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

# API Travel Rule: finalizar, reenviar, actualizar

> Con la API de Didit, cierra una transferencia Travel Rule con su hash on-chain, cancélala, reenvíala o registra la wallet de origen real.



Prompt de la API de acciones sobre transferencias de Travel Rule
        Copiar el prompt al portapapeles



      
      

\<pre>

\`Act on an existing Travel Rule transfer: report the on-chain hash to finish it, cancel it, re-run counterparty routing, replace a refused compliance email, or record the wallet the funds left from.

Endpoint:
PATCH https://verification.didit.me/v3/transactions/{transaction_id}/travel-rule/

Authentication:
Use the x-api-key header with my Didit API key. {transaction_id} is the Didit transaction uuid.

Four mutually exclusive bodies:

1\. Finish (close out after broadcasting on-chain):
\{"payment_txn_id": "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"}
\- Requires an OUTBOUND transfer in COMPLETED status - otherwise 409.
\- Moves the transfer (and its INTERNAL-rail counterpart, if any) to FINISHED and stores the hash on the transaction.
\- Over GTR, VerifyVASP or Sygna Bridge, the network learns the hash after the response, with retries (see delivery below).
\- On the TRP rail, Didit also posts the hash to the counterparty's confirmation callback.

2\. Cancel:
\{"action": "cancel"}
\- Allowed from any non-terminal status; moves the transfer (and its INTERNAL-rail counterpart, if any) to CANCELLED.
\- From a terminal status (FINISHED, CANCELLED, EXPIRED) it returns 409.
\- On an outbound TRP transfer, Didit also sends a cancellation to the counterparty.
\- Over GTR, VerifyVASP or Sygna Bridge, the network is told after the response, with retries.

3\. Resend (re-run the routing ladder):
\{"action": "resend"}
\- Allowed only on an OUTBOUND transfer in COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE, or NOT_ENOUGH_COUNTERPARTY_DATA - otherwise 409.
\- Resets the deadline and re-runs routing; a transfer whose destination wallet was declared unhosted moves to UNCONFIRMED_OWNERSHIP.
\- First give Didit a route, for example by registering the destination wallet in your address book (same chain as the transfer, or a blank chain) with the counterparty's travel_address (TRP carries BTC, ETH, and USDC on a named network), or by adding a compliance contact for the counterparty's directory entry with POST /v3/travel-rule/counterparty-contacts/, then resend.
\- Resend reuses the transfer's beneficiary_data, which you cannot change after creation except for the compliance email (body 4), so submit a new transaction to send different beneficiary data.
\- A previously recorded blockchain-analytics attribution is reused - no new lookup, no new charge.
\- Discovery runs again from the first step (internal address book, wallet attribution, network lookup, your VASP hint, then the end user); the transfer's "discovery" list shows what each step found.
\- Queued, not run inside the request: the response shows the transfer back in AWAITING_COUNTERPARTY with a "resend queued" timeline entry, and the outcome arrives as a travel_rule.status.updated webhook. A resend sent while an earlier attempt is still running is sent once that attempt settles.
\- If routing still resolves nothing, the transfer lands back in COUNTERPARTY_VASP_NOT_FOUND.

4\. Update the compliance email (the fix for reason email_undeliverable):
\{"action": "update_compliance_email", "compliance_email": "desk@bene-casp.example"}
\- Allowed only on an OUTBOUND transfer in COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE, or NOT_ENOUGH_COUNTERPARTY_DATA - otherwise 409.
\- A missing or malformed compliance_email returns 400.
\- Stores the address as this transfer's beneficiary_data.counterparty_vasp_email; it belongs to this transfer only and joins no directory entry or contact list.
\- The status does not change and the timeline gains "compliance email updated". The transfer keeps reason email_undeliverable until you send {"action": "resend"}, which sends the request to the new address.

4\. Update the originator wallet (the wallet the funds actually left from):
\{"action": "update_originator_wallet", "wallet_address": "bc1q...", "memo": ""}
\- Outbound transfers only (an inbound transfer -> 409), and never a CANCELLED or EXPIRED one (-> 409).
\- Use it when a withdrawal is broadcast from another address than the one declared, typically a UTXO withdrawal spending whichever addresses held the coins. When the transfer's UTXO inputs are known, wallet_address must be one of them (-> 400 otherwise).
\- Changes the record only: nothing is sent to the counterparty again and the status stays. chain_details.originator becomes the new wallet with source "updated", the timeline records the previous and the new wallet, and the INTERNAL-rail counterpart is updated the same way.

5\. Name the counterparty (when discovery could not):
\{"action": "beneficiary_vasp", "beneficiary_vasp": "<directory VASP id>"}
\- The id comes from GET /v3/travel-rule/vasps/.
\- Allowed only for an outbound transfer in COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE, or NOT_ENOUGH_COUNTERPARTY_DATA - otherwise 409.
\- Routes the transfer to that VASP and sends it again; automatic discovery never overrides your choice.
\- 400 if beneficiary_vasp is missing or not a valid id, 404 if no directory entry has that id.

What to read from the response:
\- The full transfer object: status, rail, direction, ownership_confirmed, deadline_at, timeline, counterparty_vasp, delivery, discovery, reason, next_actions.
\- delivery: the latest message the transfer owes the other side - kind (SEND, ANSWER, TXID, CANCEL, POLL), status (QUEUED, SENDING, RETRYING, DELIVERED, FAILED), rail, attempts, last_error, next_attempt_at, delivered_at. Failures a network may recover from are retried after 30 s, 2, 10, 30 and 60 minutes; when a first message fails for good the transfer moves to COUNTERPARTY_VASP_NOT_REACHABLE. null when the transfer never owed a message.
\- reason and next_actions say why a COUNTERPARTY_VASP_NOT_FOUND or COUNTERPARTY_VASP_NOT_REACHABLE transfer is stuck and what moves it on: email_undeliverable offers update_compliance_email then resend, delivery_failed offers resend, and a discovery reason offers select_counterparty_vasp, declare_self_hosted, add_vasp_hint and resend. Both are empty for any other status, so they clear once a resend moves the transfer on.

Order of operations for outbound transfers:
submit transaction -> wait for travel_rule.status == "COMPLETED" -> broadcast on-chain -> PATCH with payment_txn_id -> FINISHED.
Never broadcast before COMPLETED.
A transfer sent over TRUST cannot reach COMPLETED, because TRUST sends back nothing Didit can read; it stays AWAITING_COUNTERPARTY until it expires. Over GTR, VerifyVASP and Sygna Bridge, Didit reads the counterparty's answer from the network.
If the message cannot be delivered, the transfer moves to COUNTERPARTY_VASP_NOT_REACHABLE instead.

Failure modes:
\- 400 - the body has none of payment_txn_id or a supported action, update_compliance_email has a missing or malformed compliance_email, or a wallet_address or memo the transfer's chain cannot carry.
\- 409 - action not allowed from the transfer's current status or direction (see the per-action rules above).
\- 400 - action=beneficiary_vasp without a valid beneficiary_vasp.
\- 404 - unknown transaction, no Travel Rule transfer attached, or (action=beneficiary_vasp) no directory entry has that id.

Full guide: /transaction-monitoring/travel-rule#sending-a-transfer and /transaction-monitoring/travel-rule#why-a-transfer-is-stuck.`

\</pre>



      
      

Pegar en



## OpenAPI

````yaml es/openapi-25.json PATCH /v3/transactions/{transaction_id}/travel-rule/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: API de verificación de identidad. Autentícate con el encabezado x-api-key.
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/transactions/{transaction_id}/travel-rule/:
    patch:
      tags:
        - Travel Rule
      summary: >-
        Finalizar, cancelar, reenviar o actualizar la wallet del ordenante de
        una transferencia de Travel Rule
      description: >-
        Envía `payment_txn_id` para informar el hash on-chain y pasar una
        transferencia saliente COMPLETED a FINISHED (su transferencia homóloga
        del rail INTERNAL también pasa a FINISHED), `{"action": "cancel"}` para
        cancelar una transferencia que no esté en un estado final, o `{"action":
        "resend"}` para volver a enrutar una transferencia saliente bloqueada en
        COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE o
        NOT_ENOUGH_COUNTERPARTY_DATA (antes mejora los datos de la contraparte,
        por ejemplo añade una travel_address a la entrada de la wallet de
        destino). resend solo se aplica a transferencias salientes. `{"action":
        "update_compliance_email", "compliance_email": "desk@example.com"}`
        reemplaza el correo de cumplimiento de una transferencia saliente que
        esté en uno de esos tres estados, la solución para `reason:
        email_undeliverable`: el estado no cambia y el siguiente `resend` envía
        la solicitud a esa dirección. Un reenvío se pone en cola, no se ejecuta
        dentro de la solicitud: la respuesta muestra la transferencia de nuevo
        en AWAITING_COUNTERPARTY con una entrada `resend queued` en la
        cronología y una `delivery` en cola, y el lugar al que se envió llega
        como un webhook `travel_rule.status.updated`. Cuando la transferencia se
        envió por GTR, VerifyVASP o Sygna Bridge, la red recibe el hash on-chain
        o la cancelación después de la respuesta, con reintentos; `delivery`
        muestra el estado de ese mensaje. `{"action":
        "update_originator_wallet", "wallet_address": "..."}` registra la wallet
        desde la que realmente salieron los fondos en una transferencia
        saliente, por ejemplo la dirección desde la que se difundió un retiro
        UTXO en lugar de la wallet principal que declaraste. Solo cambia el
        registro: no se vuelve a enviar nada a la contraparte y el estado se
        mantiene. El ordenante pasa a ser `chain_details.originator` con
        `source: updated`, el cambio se añade a la `timeline` con la wallet
        anterior y la nueva, y la transferencia homóloga del rail INTERNAL se
        actualiza de la misma forma. `{"action": "beneficiary_vasp",
        "beneficiary_vasp": "<directory VASP id>"}` te permite indicar tú mismo
        la contraparte cuando el descubrimiento no pudo hacerlo, en una
        transferencia saliente en COUNTERPARTY_VASP_NOT_FOUND,
        COUNTERPARTY_VASP_NOT_REACHABLE o NOT_ENOUGH_COUNTERPARTY_DATA: la
        transferencia se enruta a ese VASP y se vuelve a enviar.
      operationId: patchTravelRuleTransfer
      parameters:
        - name: transaction_id
          in: path
          required: true
          description: >-
            UUID estable de Didit de la transacción a la que pertenece la
            transferencia.
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TravelRuleTransferPatchRequest'
            examples:
              Finish:
                value:
                  payment_txn_id: 0xchainhash
              Cancel:
                value:
                  action: cancel
              Resend:
                value:
                  action: resend
              Update compliance email:
                value:
                  action: update_compliance_email
                  compliance_email: desk@example.com
              Update originator wallet:
                value:
                  action: update_originator_wallet
                  wallet_address: bc1qOriginatorInputAddress01
              Name the counterparty:
                value:
                  action: beneficiary_vasp
                  beneficiary_vasp: 9f1c2b34-5d6e-4f70-8a91-b2c3d4e5f607
      responses:
        '200':
          description: >-
            La transferencia actualizada. Después de `update_compliance_email`,
            su estado no cambia y conserva `reason: email_undeliverable` hasta
            el siguiente `resend`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TravelRuleTransferDetail'
        '400':
          description: >-
            No se proporcionó ni payment_txn_id ni una acción admitida, falta
            `compliance_email` o no es una dirección de correo electrónico en
            `update_compliance_email`, o, para `update_originator_wallet`, falta
            wallet_address, hay una wallet o un memo que la cadena de la
            transferencia no puede transportar o hay una wallet que no es una de
            las entradas UTXO de la transferencia, o falta `beneficiary_vasp` o
            no es un ID de VASP válido del directorio.
          content:
            application/json:
              examples:
                No action:
                  value:
                    detail:
                      - >-
                        Provide payment_txn_id, action=cancel, action=resend,
                        action=beneficiary_vasp, action=update_originator_wallet
                        or action=update_compliance_email.
                Invalid compliance email:
                  value:
                    compliance_email:
                      - Enter a valid email address.
        '404':
          description: >-
            Transacción desconocida, la transacción no tiene ninguna
            transferencia de Travel Rule o (acción `beneficiary_vasp`) ninguna
            entrada del directorio tiene ese id.
        '409':
          description: >-
            La transferencia no está en un estado que permita esta operación (p.
            ej., no está en COMPLETED/saliente para finalizar, ya está en un
            estado final para cancelar, o no es una transferencia saliente en un
            estado que permita el reenvío para reenviar).
            `update_compliance_email` responde `409` para una transferencia
            entrante, y para una saliente fuera de COUNTERPARTY_VASP_NOT_FOUND,
            COUNTERPARTY_VASP_NOT_REACHABLE y NOT_ENOUGH_COUNTERPARTY_DATA.
            `update_originator_wallet` responde `409` para una transferencia
            entrante, cancelada o expirada. `beneficiary_vasp` responde `409`
            salvo que la transferencia sea saliente y esté en
            COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE o
            NOT_ENOUGH_COUNTERPARTY_DATA.
          content:
            application/json:
              examples:
                Cancel from a terminal status:
                  value:
                    detail: Transfer is already in a terminal state.
                Resend not allowed:
                  value:
                    detail: Transfer cannot be resent from its current state.
                Finish not allowed:
                  value:
                    detail: >-
                      Transfer must be an outbound transfer in COMPLETED status
                      to finish.
                Compliance email cannot change:
                  value:
                    detail: >-
                      The compliance email of this transfer cannot change from
                      its current state.
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: >-
            curl -X PATCH
            https://verification.didit.me/v3/transactions/{transaction_id}/travel-rule/
            \
              -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \
              -d '{"payment_txn_id": "0xchainhash"}'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # Reads DIDIT_API_KEY.
            client = Didit()

            result = client.transactions.travel_rule.update_transfer(
                "11111111-2222-3333-4444-555555555555",
                payment_txn_id="0xchainhash",
            )
            print(result)
        - lang: javascript
          label: Node.js
          source: >-
            import Didit from "@didit-protocol/sdk-node";


            // Reads DIDIT_API_KEY.

            const didit = new Didit();


            const result = await
            didit.transactions.travelRule.updateTransfer("11111111-2222-3333-4444-555555555555",
            {
              payment_txn_id: "0xchainhash",
            });

            console.log(result);
        - lang: go
          label: Go
          source: "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.TravelRule.UpdateTransfer(ctx, \"11111111-2222-3333-4444-555555555555\", didit.TravelRuleTransferPatchRequest{\n\tPaymentTxnID: didit.String(\"0xchainhash\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
        - lang: java
          label: Java
          source: >-
            import me.didit.Didit;

            import me.didit.types.TravelRuleTransferPatchRequest;


            // Reads DIDIT_API_KEY.

            Didit client = new Didit();


            var result =
            client.transactions().travelRule().updateTransfer("11111111-2222-3333-4444-555555555555",
            TravelRuleTransferPatchRequest.builder()
                    .paymentTxnId("0xchainhash")
                    .build());
            System.out.println(result);
        - lang: php
          label: PHP
          source: >-
            <?php


            require 'vendor/autoload.php';


            use Didit\DiditClient;


            // Reads DIDIT_API_KEY.

            $didit = new DiditClient();


            $result =
            $didit->transactions->travelRule->updateTransfer('11111111-2222-3333-4444-555555555555',
            [
                'payment_txn_id' => '0xchainhash',
            ]);

            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

            # Reads DIDIT_API_KEY.
            didit = Didit::Client.new

            result = didit.transactions.travel_rule.update_transfer(
              "11111111-2222-3333-4444-555555555555",
              payment_txn_id: "0xchainhash"
            )
            puts result.to_h
        - lang: csharp
          label: .NET
          source: >-
            using System;

            using System.Text.Json;

            using Didit;


            // Reads DIDIT_API_KEY.

            using var client = new DiditClient();


            var result = await
            client.Transactions.TravelRule.UpdateTransferAsync("11111111-2222-3333-4444-555555555555",
            new TravelRuleTransferPatchRequest

            {
                PaymentTxnId = "0xchainhash",
            });

            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  schemas:
    TravelRuleTransferPatchRequest:
      type: object
      description: >-
        Proporciona exactamente uno de estos: payment_txn_id (finalizar),
        action=cancel, action=resend, action=update_compliance_email con
        compliance_email, action=update_originator_wallet con wallet_address, o
        action=beneficiary_vasp con beneficiary_vasp.
      properties:
        payment_txn_id:
          type: string
          description: >-
            El hash de la transacción on-chain. Requiere que la transferencia
            sea saliente y esté en estado COMPLETED.
        action:
          type: string
          enum:
            - cancel
            - resend
            - update_compliance_email
            - update_originator_wallet
            - beneficiary_vasp
          description: >-
            "cancel" cancela una transferencia que aún no está en un estado
            final. "resend" vuelve a ejecutar el enrutamiento de una
            transferencia saliente bloqueada en COUNTERPARTY_VASP_NOT_FOUND,
            COUNTERPARTY_VASP_NOT_REACHABLE o NOT_ENOUGH_COUNTERPARTY_DATA.
            "update_compliance_email" sustituye el correo electrónico de
            cumplimiento al que se envía la solicitud, en una transferencia
            saliente que esté en uno de esos tres estados; envía "resend"
            después. "update_originator_wallet" registra la wallet desde la que
            realmente salieron los fondos (`wallet_address`, `memo`).
            "beneficiary_vasp" te permite indicar tú mismo el VASP de la
            contraparte (requiere `beneficiary_vasp`) para una transferencia
            saliente que esté en uno de esos estados: se enruta a ese VASP y se
            vuelve a enviar.
        compliance_email:
          type: string
          format: email
          maxLength: 254
          description: >-
            Obligatorio con `action: update_compliance_email`. Se guarda como
            `beneficiary_data.counterparty_vasp_email` de esta transferencia:
            pertenece solo a esta transferencia y no se añade a ninguna entrada
            del directorio ni a ninguna lista de contactos.
        wallet_address:
          type: string
          maxLength: 128
          description: >-
            Con `action: update_originator_wallet`: la wallet de la que salieron
            los fondos. Cuando se conocen las entradas UTXO de la transferencia,
            debe ser una de ellas.
        memo:
          type: string
          maxLength: 256
          description: >-
            Con `action: update_originator_wallet`: el memo o la etiqueta de la
            wallet en una red con memo. Opcional.
        beneficiary_vasp:
          type: string
          format: uuid
          description: >-
            Obligatorio con action=beneficiary_vasp: el `id` de un VASP del
            directorio, obtenido de `GET /v3/travel-rule/vasps/`. Tu elección
            prevalece sobre todos los pasos de descubrimiento automático, que
            nunca la anulan.
    TravelRuleTransferDetail:
      type: object
      description: >-
        Objeto de transferencia completo que devuelven los endpoints de
        confirmación de propiedad y de finalizar/cancelar. Mientras la propiedad
        de la wallet de una transferencia entrante no esté confirmada, los
        `originator_data` y `beneficiary_data` de la contraparte se devuelven
        enmascarados (se conserva la primera letra de cada palabra; la wallet,
        la cadena y el enrutamiento del VASP siguen siendo legibles) y
        `data_masked` es true.
      properties:
        uuid:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - AWAITING_COUNTERPARTY
            - ON_HOLD
            - COMPLETED
            - FINISHED
            - CANCELLED
            - EXPIRED
            - COUNTERPARTY_MISMATCHED_DATA
            - COUNTERPARTY_VASP_NOT_FOUND
            - COUNTERPARTY_VASP_NOT_REACHABLE
            - UNCONFIRMED_OWNERSHIP
            - COUNTERPARTY_VASP_GENERAL_DECLINE
            - NOT_ENOUGH_COUNTERPARTY_DATA
            - NOT_APPLICABLE
        direction:
          type: string
          enum:
            - INBOUND
            - OUTBOUND
        rail:
          type: string
          nullable: true
          enum:
            - INTERNAL
            - TRP
            - GTR
            - TRUST
            - VERIFYVASP
            - SYGNA
            - EMAIL
            - TEST_VASP
            - null
          description: >-
            La vía por la que se enrutó la transferencia, o null cuando no se
            seleccionó ninguna vía (por ejemplo, por debajo del umbral, con una
            wallet sin custodia de la contraparte, con un registro posterior al
            depósito o sin una contraparte alcanzable). INTERNAL significa que
            ambas partes son aplicaciones de Didit; EMAIL significa que se llegó
            a la contraparte mediante un enlace de recogida enviado por correo
            electrónico. TEST_VASP significa que el VASP de prueba de Didit
            respondió a la transferencia del sandbox. Por GTR, VERIFYVASP y
            SYGNA, Didit lee la respuesta de la contraparte en la respuesta de
            la red o consultándola cada 5 minutos. TRUST solo envía, por lo que
            una transferencia por TRUST permanece en AWAITING_COUNTERPARTY hasta
            que expira. Una vía de red solo se usa cuando has conectado tu
            propia membresía a esa red. Se elige después de que la creación de
            la transacción responde, por lo que es null en esa respuesta.
        protocol:
          type: string
          nullable: true
        ivms_version:
          type: string
          example: ivms101.2023
        required:
          type: boolean
        ownership_confirmed:
          type: boolean
          nullable: true
        deadline_at:
          type: string
          format: date-time
          nullable: true
        timeline:
          type: array
          items:
            type: object
            properties:
              status:
                type: string
              at:
                type: string
                format: date-time
              detail:
                type: string
              name_match:
                allOf:
                  - $ref: '#/components/schemas/TravelRuleNameMatch'
                nullable: true
                description: >-
                  La comparación de nombres que decidió esta entrada, junto a
                  `detail`. No aparece en las entradas que no compararon ningún
                  nombre.
              reason:
                type: string
                description: >-
                  Presente solo en la entrada de una transición causada por una
                  entrega fallida: `email_undeliverable` o `delivery_failed`, el
                  valor que informa el `reason` de la transferencia.
        counterparty_vasp:
          type: object
          nullable: true
          properties:
            name:
              type: string
            lei:
              type: string
            dd_score:
              type: integer
              description: >-
                Puntuación de diligencia debida de 0 a 100, donde un valor más
                alto es mejor. Usa la misma escala que el directorio de VASP.
            dd_score_breakdown:
              type: object
              description: >-
                Contribuciones de cada componente a dd_score, un objeto por
                componente como en el directorio de VASP (jurisdiction,
                verification, protocol, lei, history, essentials,
                responsiveness), cada uno con {points, max, reason, detail}. {}
                hasta que se haya evaluado la contraparte.
              additionalProperties:
                type: object
                properties:
                  points:
                    type: number
                    description: Puntos otorgados a este componente.
                  max:
                    type: integer
                    description: Puntos máximos que puede otorgar este componente.
                  reason:
                    type: string
                    description: Código legible por máquina del veredicto del componente.
                  detail:
                    type: string
                    description: Motivo legible de los puntos asignados.
            dd_assessed_at:
              type: string
              format: date-time
              nullable: true
              description: >-
                Cuándo se ejecutó por última vez la evaluación de diligencia
                debida. Nulo hasta que se haya evaluado la contraparte.
        originator_data:
          type: object
          description: >-
            Parte ordenante. En una transferencia entrante, los valores de la
            contraparte están enmascarados hasta que se confirma la propiedad.
        beneficiary_data:
          type: object
          description: >-
            Parte beneficiaria. En una transferencia entrante, los valores de la
            contraparte están enmascarados hasta que se confirma la propiedad.
        name_match:
          allOf:
            - $ref: '#/components/schemas/TravelRuleNameMatch'
          nullable: true
          description: >-
            La comparación de nombres que decidió la transferencia, o null hasta
            que se haya ejecutado una. Mientras las partes están enmascaradas, y
            en la copia del otro cliente de un intercambio INTERNAL,
            `transfer_name`, `compared_name`, `matched_names` y
            `mismatched_names` se ocultan. `score` y `matched` pueden no
            coincidir: `matched` sigue el nivel de exigencia y `score` es la
            similitud entre los dos nombres completos.
        data_match:
          $ref: '#/components/schemas/TravelRuleDataMatch'
        mismatched_fields:
          type: array
          items:
            type: string
          description: >-
            Atajo para `data_match.mismatched_fields`. Vacío cuando nada
            difiere.
        data_unmasked:
          $ref: '#/components/schemas/TravelRuleDataUnmasked'
        data_masked:
          type: boolean
          description: >-
            True mientras los datos personales de la contraparte están
            enmascarados en esta respuesta.
        created_at:
          type: string
          format: date-time
        delivery:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/TravelRuleDelivery'
          description: >-
            Estado del último mensaje que esta transferencia debe a la otra
            parte. Es nulo cuando la transferencia nunca debió ninguno (por
            ejemplo, por debajo de `threshold_amount`, una wallet sin custodia
            declarada o un registro de sunrise).
        discovery:
          type: array
          description: >-
            Cómo buscó Didit la contraparte, con una entrada por cada paso
            ejecutado. Vacío cuando no se ejecutó ningún descubrimiento, por
            ejemplo, en una transferencia entrante.
          items:
            $ref: '#/components/schemas/TravelRuleDiscoveryStep'
        reason:
          type: string
          description: >-
            Por qué está bloqueada una transferencia
            `COUNTERPARTY_VASP_NOT_FOUND` o `COUNTERPARTY_VASP_NOT_REACHABLE`;
            `""` para cualquier otro estado. Primero lo determina una entrega
            fallida, solo en `COUNTERPARTY_VASP_NOT_REACHABLE`:
            `email_undeliverable` (el proveedor de correo rechazó el correo de
            cumplimiento y no queda ninguna dirección que probar: al enviarlo,
            en un recordatorio o como rebote permanente notificado más tarde) o
            `delivery_failed` (el canal que realizaba la entrega falló de forma
            definitiva: un canal de red rechazó el mensaje o agotó los
            reintentos, un host de identidad `TRP` no respondió o el host `TRP`
            de la contraparte no aceptó la consulta). En caso contrario, lo
            determina la traza `discovery`: `awaiting_end_user` (ningún paso
            indicó una contraparte a la que Didit pueda llegar),
            `directory_match_no_route` (un paso indicó un VASP del directorio
            que no tiene ruta), `picked_member_without_proven_wallet` (el
            usuario final eligió un cliente de Didit que no ha demostrado el
            control de la wallet) o `no_directory_match` cuando la traza no da
            ningún otro motivo. Un reenvío hace avanzar la transferencia, por lo
            que el motivo se borra. Consulta [Por qué está bloqueada una
            transferencia](/es/transaction-monitoring/travel-rule#por-qué-una-transferencia-está-bloqueada).
        next_actions:
          type: array
          description: >-
            Qué hace avanzar la transferencia; `[]` para cualquier estado que no
            sea `COUNTERPARTY_VASP_NOT_FOUND` o
            `COUNTERPARTY_VASP_NOT_REACHABLE`. `email_undeliverable` ofrece
            `update_compliance_email` y después `resend`. `delivery_failed`
            ofrece `resend`. Un motivo de descubrimiento ofrece
            `select_counterparty_vasp`, `declare_self_hosted`, `add_vasp_hint` y
            `resend`.
          items:
            $ref: '#/components/schemas/TravelRuleNextAction'
        chain_details:
          $ref: '#/components/schemas/TravelRuleChainDetails'
    TravelRuleNameMatch:
      type: object
      nullable: true
      description: >-
        La comparación de nombres que decidió la transferencia, o null hasta que
        se haya ejecutado una. Mientras las partes están enmascaradas, y en la
        copia del otro cliente de un intercambio INTERNAL, `transfer_name`,
        `compared_name`, `matched_names` y `mismatched_names` se ocultan.
        `score` y `matched` pueden no coincidir: `matched` sigue el nivel de
        exigencia y `score` es la similitud entre los dos nombres completos.
      properties:
        score:
          type: integer
          minimum: 0
          maximum: 100
          description: >-
            Similitud de los dos nombres completos, de 0 a 100. 0 cuando alguno
            de los nombres está vacío.
        matched:
          type: boolean
          description: >-
            Si los nombres cumplen `strictness`. El resultado de la
            transferencia depende de `data_match`, que compara todos los campos,
            por lo que una transferencia puede ser COUNTERPARTY_MISMATCHED_DATA
            aunque este valor sea true.
        method:
          type: string
          enum:
            - none
            - exact_token
            - token_subset
            - token_containment
            - sequence_ratio
          description: >-
            Cómo se decidió `matched`: none (`NONE`), exact_token (`STRICT`),
            token_subset (`DEFAULT`), token_containment (`CONTAINS`) o
            sequence_ratio (`FUZZY`).
        strictness:
          type: string
          enum:
            - NONE
            - STRICT
            - CONTAINS
            - DEFAULT
            - FUZZY
        compared_with:
          type: string
          enum:
            - wallet_holder
            - counterparty_vasp
          description: >-
            wallet_holder: el titular registrado para la wallet.
            counterparty_vasp: el nombre que respondió la contraparte en la
            página de respuesta por correo electrónico, o la respuesta del Didit
            Test VASP en sandbox.
        transfer_name:
          type: string
          description: El nombre que figura en la transferencia.
        compared_name:
          type: string
          description: El nombre con el que se comparó.
        matched_names:
          type: array
          items:
            type: string
          description: Palabras de `transfer_name` que se encuentran en `compared_name`.
        mismatched_names:
          type: array
          items:
            type: string
          description: >-
            Palabras de `transfer_name` que faltan en `compared_name` y, a
            continuación, palabras de `compared_name` que faltan en
            `transfer_name`.
    TravelRuleDataMatch:
      type: object
      nullable: true
      description: >-
        Comparación campo a campo de los datos de las partes de la transferencia
        con lo que la otra parte sabe del titular de la wallet. Indica campos y
        resultados, nunca valores, por lo que sigue siendo legible mientras los
        datos de la contraparte están enmascarados. Es null hasta que se realiza
        una comparación.
      properties:
        matched:
          type: boolean
          description: True cuando ningún campo comparado difiere.
        mismatched_fields:
          type: array
          items:
            type: string
            enum:
              - name
              - date_of_birth
              - address
              - account
          description: Los campos que difieren.
        fields:
          type: object
          description: >-
            Una entrada por campo comparado para el tipo de entidad de la parte
            (`name`, `date_of_birth`, `address`, `account`; una empresa no tiene
            `date_of_birth`).
          additionalProperties:
            type: object
            properties:
              result:
                type: string
                enum:
                  - matched
                  - mismatched
                  - not_compared
                description: >-
                  `not_compared` cuando la regla es `NONE` o alguna de las dos
                  partes no tiene valor para el campo.
              strictness:
                type: string
                enum:
                  - NONE
                  - STRICT
                  - CONTAINS
                  - DEFAULT
                  - FUZZY
    TravelRuleDataUnmasked:
      type: object
      nullable: true
      description: >-
        Registro de auditoría del momento en que se desenmascararon los datos de
        la contraparte. Es null mientras los datos siguen enmascarados, y en las
        transferencias salientes.
      properties:
        at:
          type: string
          format: date-time
        reason:
          type: string
          enum:
            - ownership_confirmed
            - wallet_proof
            - address_book_match
            - own_verified_wallet
            - inquiry_approved
            - known_payment_method
            - travel_address
          description: >-
            Qué confirmó la propiedad: ownership_confirmed (tu confirmación a
            través de la consola o de la API), wallet_proof (una prueba de
            wallet en el widget o una transferencia entrante INTERNAL; se
            establece al crearla), address_book_match (una wallet verificada de
            la libreta de direcciones), own_verified_wallet (la propia wallet
            verificada de tu usuario), inquiry_approved (tu aprobación de una
            consulta TRP entrante o de un mensaje GTR o Sygna),
            known_payment_method (una wallet con la que tu usuario ya pagó) o
            travel_address (la travel address propia de cada wallet identificó
            la wallet).
        actor:
          type: string
          description: >-
            Quién lo confirmó: el correo electrónico del usuario de la consola o
            la etiqueta de la clave de API. Vacío en una decisión automática.
    TravelRuleDelivery:
      type: object
      description: >-
        Estado del último mensaje que la transferencia debe a la otra parte.
        Didit contacta con la contraparte después de que la solicitud que creó o
        modificó la transferencia haya respondido, así que este objeto indica si
        ese mensaje llegó: en cola, en envío, a la espera de reintentarse tras
        un error, entregado o fallido. Un fallo del que la red aún puede
        recuperarse (sin respuesta a tiempo, conexión fallida, HTTP `408`, `429`
        o `5xx`) se reintenta a los 30 segundos, 2 minutos, 10 minutos, 30
        minutos y 1 hora. Cuando un primer mensaje (`kind: SEND`) falla de forma
        definitiva, porque la red lo rechazó o porque también falló el sexto
        intento, la transferencia pasa a `COUNTERPARTY_VASP_NOT_REACHABLE` con
        `last_error` en su `timeline`; cualquier otro mensaje que falle de forma
        definitiva se registra en el `timeline`. El `status` de la transferencia
        sigue siendo la fuente de verdad del intercambio en sí.
      required:
        - kind
        - status
        - rail
        - attempts
        - last_error
        - next_attempt_at
        - delivered_at
      properties:
        kind:
          type: string
          enum:
            - SEND
            - ANSWER
            - TXID
            - CANCEL
            - POLL
          description: >-
            Qué transporta el mensaje. `SEND`: el primer mensaje de la
            transferencia a la contraparte (saliente; el canal se elige al
            enviarlo). `ANSWER`: tu aceptación o rechazo, que se debe a la red
            que lo solicitó (entrante). `TXID`: el hash de la transacción
            on-chain, después de que completes la transferencia. `CANCEL`: la
            cancelación, después de que la canceles. `POLL`: una consulta de
            estado a una red que la ofrece, repetida cada 5 minutos mientras la
            transferencia espera a la contraparte.
        status:
          type: string
          enum:
            - QUEUED
            - SENDING
            - RETRYING
            - DELIVERED
            - FAILED
          description: >-
            `QUEUED`: en espera de envío. `SENDING`: hay un intento en curso.
            `RETRYING`: un intento falló y el siguiente se ejecuta en
            `next_attempt_at`. `DELIVERED`: la otra parte aceptó el mensaje.
            `FAILED`: la otra parte lo rechazó, o falló el último intento.
        rail:
          type: string
          enum:
            - INTERNAL
            - TRP
            - GTR
            - TRUST
            - VERIFYVASP
            - SYGNA
            - EMAIL
            - ''
          description: >-
            La vía que transporta el mensaje. Vacía hasta que Didit elige una
            para un primer mensaje.
        attempts:
          type: integer
          minimum: 0
          description: >-
            Intentos realizados hasta ahora para este mensaje. Un mensaje que no
            es una consulta de estado se intenta como máximo 6 veces.
        last_error:
          type: string
          description: >-
            El tipo de fallo que tuvo el último intento, `""` si no hubo
            ninguno: por ejemplo `email undeliverable`, `trp identity endpoint
            unreachable` o `trp transfer inquiry delivery failed`. Nunca incluye
            la respuesta de la propia contraparte, que permanece en el
            `timeline` de la transferencia.

            Cuando GTR responde con un error, se incluyen su propio código de
            estado y su mensaje. Los cuerpos de respuesta nunca se incluyen.
          example: email undeliverable
        next_attempt_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            Fecha y hora del próximo intento mientras el mensaje está en
            `QUEUED` o `RETRYING`.
        delivered_at:
          type: string
          format: date-time
          nullable: true
          description: Fecha y hora en que el otro extremo aceptó el mensaje.
    TravelRuleDiscoveryStep:
      type: object
      description: >-
        Un paso del descubrimiento de contraparte que Didit ejecutó para una
        transferencia saliente, en el orden en que los ejecutó. El primer paso
        que identifica un VASP con una ruta finaliza la cadena.
      properties:
        step:
          type: string
          enum:
            - internal_address_book
            - wallet_attribution
            - network_lookup
            - customer_hint
            - end_user
          description: >-
            `internal_address_book`: otro cliente de Didit que demostró tener el
            control de la wallet de destino. `wallet_attribution`: la atribución
            de la wallet según la analítica de blockchain. `network_lookup`: una
            red que puede indicar qué VASP custodia la dirección.
            `customer_hint`: el nombre, el LEI o la jurisdicción del VASP que
            enviaste en `beneficiary_data`. `end_user`: la contraparte que
            eligió el usuario final (o tú), o la solicitud para que se elija
            una.
        outcome:
          type: string
          enum:
            - match
            - miss
            - skipped
          description: >-
            `match`: el paso identificó una contraparte. `miss`: se ejecutó y no
            encontró ninguna. `skipped`: no se pudo ejecutar, y `reason` indica
            el motivo.
        reason:
          type: string
          description: >-
            Motivo legible por máquina, `""` cuando hay coincidencia:
            `no_proven_internal_wallet`, `attribution_disabled`,
            `already_attributed`, `no_attributed_entity`,
            `directory_match_no_route`, `gtr_address_lookup_runs_on_dispatch`,
            `no_membership`, `network_switched_off`,
            `no_network_address_lookup`, `no_directory_match`,
            `awaiting_end_user` o `picked_member_without_proven_wallet`.
        vasp:
          type: string
          format: uuid
          nullable: true
          description: El VASP del directorio que indicó el paso, cuando indicó uno.
        rail:
          type: string
          nullable: true
          description: La vía que llega a esa contraparte, cuando el paso encontró una.
        at:
          type: string
          format: date-time
    TravelRuleNextAction:
      type: object
      description: >-
        Algo que hace avanzar una transferencia en estado
        `COUNTERPARTY_VASP_NOT_FOUND` o `COUNTERPARTY_VASP_NOT_REACHABLE`.
        Consulta [Por qué una transferencia está
        bloqueada](/es/transaction-monitoring/travel-rule#por-qué-una-transferencia-está-bloqueada).
      properties:
        action:
          type: string
          enum:
            - select_counterparty_vasp
            - declare_self_hosted
            - add_vasp_hint
            - update_compliance_email
            - resend
          description: >-
            `select_counterparty_vasp`: el usuario final elige el VASP de
            destino en el widget de propiedad de la wallet, o haces un PATCH con
            `action=beneficiary_vasp`. `declare_self_hosted`: el usuario final
            declara en el widget que la wallet es sin custodia. `add_vasp_hint`:
            indica a Didit quién es la contraparte con un nombre de VASP, un LEI
            o una travel address (por ejemplo, una `travel_address` en la
            entrada de la libreta de direcciones de la wallet de destino) y
            vuelve a enviarla. `update_compliance_email` y `resend` son valores
            de `action` de `PATCH
            /v3/transactions/{transaction_id}/travel-rule/`: vuelve a indicar el
            correo electrónico de cumplimiento de la contraparte y vuelve a
            ejecutar el enrutamiento.
        url:
          type: string
          format: uri
          description: >-
            El enlace del widget de propiedad de la wallet, en
            `select_counterparty_vasp` y `declare_self_hosted` mientras la
            transferencia tiene una sesión de widget abierta.
      required:
        - action
    TravelRuleChainDetails:
      type: object
      description: >-
        Cómo identifica la cadena de la transferencia sus dos wallets, cuando no
        se trata simplemente de una dirección que paga a otra. Vacío (`{}`) en
        una transferencia de una cadena basada en cuentas (EVM, Solana, Tron),
        donde las dos direcciones son las wallets. La coincidencia, el
        enrutamiento y la libreta de direcciones leen las wallets primero de
        aquí.
      properties:
        chain:
          type: string
          description: >-
            Cadena canónica, p. ej., `BTC`, `XRP` o `LIGHTNING` para una
            transferencia Lightning.
        shape:
          type: string
          enum:
            - utxo
            - memo
            - lightning
        originator:
          $ref: '#/components/schemas/TravelRuleChainSide'
        beneficiary:
          $ref: '#/components/schemas/TravelRuleChainSide'
        utxo:
          type: object
          description: >-
            En una transferencia UTXO: las entradas y salidas tal como se
            almacenan (importes como cadenas decimales) y cómo interpretó Didit
            cada salida.
          properties:
            inputs:
              type: array
              items:
                $ref: '#/components/schemas/TravelRuleUtxoEntry'
            outputs:
              type: array
              items:
                $ref: '#/components/schemas/TravelRuleUtxoEntry'
            change_output_indexes:
              type: array
              items:
                type: integer
              description: Salidas que devuelven fondos a una dirección de entrada.
            beneficiary_output_index:
              type: integer
              nullable: true
              description: >-
                La salida que paga al beneficiario; null cuando no se pudo
                distinguir ninguna.
        lightning:
          type: object
          description: >-
            En una transferencia Lightning: lo que indica la solicitud de pago.
            Siempre `kind` (`bolt11`, `bolt12_offer`, `bolt12_invoice`,
            `bolt12_invoice_request`, `lnurl`, `lightning_address`, `node_id` o
            `unknown`); una factura BOLT11 añade `network`, `payee_node_id`,
            `payment_hash`, `amount_msat`, `created_at` y `expires_at`; una
            cadena BOLT12, `blinded_paths` y `payee_node_id`; una LNURL o una
            Lightning Address, su `domain`. No se resuelve nada a través de la
            red: la solicitud solo se decodifica.
          additionalProperties: true
        warnings:
          type: array
          items:
            type: string
            enum:
              - declared_originator_not_an_input
              - declared_beneficiary_not_an_output
              - beneficiary_output_ambiguous
              - beneficiary_output_amount_differs
          description: >-
            Incoherencias UTXO que conviene revisar: el ordenante declarado no
            es una entrada, el beneficiario declarado no es una salida, no se
            pudo distinguir una única salida del beneficiario o la salida del
            beneficiario paga un importe distinto del que indica la transacción.
        not_applicable_reason:
          type: string
          enum:
            - LIGHTNING_NO_PAYEE_IDENTIFIER
            - LIGHTNING_BOLT12_BLINDED_PAYEE
            - LIGHTNING_LNURL_NAMES_NO_PAYEE
          description: >-
            En una transferencia Lightning saliente cuya solicitud de pago no
            indica ningún beneficiario: por qué la transferencia es
            `NOT_APPLICABLE`. `LIGHTNING_NO_PAYEE_IDENTIFIER` (la solicitud no
            indica ningún nodo beneficiario o no se pudo decodificar),
            `LIGHTNING_BOLT12_BLINDED_PAYEE` (la oferta oculta su beneficiario
            tras rutas cegadas), `LIGHTNING_LNURL_NAMES_NO_PAYEE` (una LNURL
            indica un servicio, no un beneficiario). El mismo código abre la
            última entrada del `timeline` de la transferencia.
    TravelRuleChainSide:
      type: object
      description: >-
        La wallet de una de las partes tal como Didit la resolvió a partir de
        los datos de la cadena.
      properties:
        address:
          type: string
          description: >-
            La wallet. En una red con memo, la dirección clásica (una X-address
            de XRP se divide en su dirección clásica y su tag); en Lightning, el
            ID de nodo del beneficiario o la Lightning Address.
        memo:
          type: string
          description: >-
            La etiqueta de destino o memo que forma parte de la wallet; `""` si
            no hay ninguno.
        source:
          type: string
          enum:
            - declared
            - x_address
            - largest_input
            - only_non_change_output
            - amount_match
            - invoice_payee
            - updated
          description: >-
            Origen de la wallet: `declared` (tu solicitud), `x_address`
            (extraída de una X-address de XRP), `largest_input` (la dirección de
            entrada UTXO que más aportó), `only_non_change_output` (la única
            salida UTXO que no es cambio), `amount_match` (la única salida UTXO
            que paga el importe de la transferencia), `invoice_payee` (el
            beneficiario que indica una solicitud de pago Lightning), `updated`
            (establecida más tarde con `action: update_originator_wallet`).
    TravelRuleUtxoEntry:
      type: object
      description: >-
        Una entrada o salida de una transacción UTXO, tal como la registró la
        cadena.
      required:
        - address
      properties:
        address:
          type: string
          maxLength: 128
        amount:
          type: string
          nullable: true
          description: >-
            Cadena decimal en la unidad propia de la moneda (BTC, no satoshis).
            Opcional.
          example: '0.0125'
        txid:
          type: string
          maxLength: 128
          description: Opcional. La transacción que gasta una entrada.
        vout:
          type: integer
          nullable: true
          minimum: 0
          description: Opcional. El índice de la salida que gasta una entrada.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        La clave de API de tu aplicación, que encontrarás en Developers -> API
        keys en la Business Console. La clave principal tiene acceso completo.
        Una clave con nombre puede tener un alcance limitado: ninguno, lectura o
        escritura por recurso, limitada a algunos flujos o a sesiones aprobadas,
        a una lista de direcciones IP y a una fecha de caducidad. 401 significa
        que la clave es incorrecta, se revocó o expiró; 403 significa que no se
        envió ninguna clave, que la clave no tiene acceso a este recurso o
        acción, o que la solicitud provino de una dirección fuera de su lista de
        IP; 404 en una ruta de sesión significa que la sesión está fuera de los
        flujos o estados de la clave. Una clave sin acceso a contenido
        multimedia recibe las URL de imágenes, videos y PDF como null, y una
        clave sin permiso de escritura en sesiones recibe los enlaces y tokens
        de sesión como null. Consulta https://docs.didit.me/console/api-keys.

````

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