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

# Trigger Test VASP Inbound Transfer

> Sandbox applications only. The Didit Test VASP sends your application an inbound Travel Rule transfer, so you can exercise the receiving side of an exchange end to end before going live. The transfer is booked and decided by the same logic a real inbound transfer from a network runs against your wallet address book, so the inbox, the decision and the wallet ownership flow behave as they do live. Nothing leaves Didit. A live application receives 400. Send the same `reference` again to get the transfer the first call booked instead of a second one.



Trigger Test VASP Inbound Transfer API Prompt
        Copy prompt to clipboard



      
      

\<pre>

\`Make the Didit Test VASP send my sandbox application an inbound Travel Rule transfer, to exercise the receiving side of an exchange before going live.

Endpoint:
POST https://verification.didit.me/v3/travel-rule/test-vasp/inbound/

Authentication:
Use the x-api-key header with my SANDBOX application's API key. A live application receives 400.

Request body (application/json):
\{
"beneficiary_wallet_address": "0xYourSandboxWallet",  // required: the destination wallet address
"scenario": "accept",                                // optional: accept (default) or name_mismatch
"chain": "ETH",                                      // optional
"amount": "1",                                       // optional, decimal string
"currency": "ETH",                                   // optional
"reference": "demo-001"                              // optional: repeat calls with it return the first transfer
}

Behavior:
\- The transfer is decided by the same logic a real inbound transfer runs, against my wallet address book: a verified wallet with the holder's name completes, an unverified wallet waits for ownership, a wallet with no matching address book entry is booked ON_HOLD, and name_mismatch ends as COUNTERPARTY_MISMATCHED_DATA.
\- Nothing leaves Didit. travel_rule.status.updated webhooks fire with environment "sandbox", test_vasp true and the scenario name.

What to read from the response:
\- transaction_id, txn_id - the booked inbound transaction.
\- travel_rule_status and detail - how my application decided it.
\- travel_rule - the full transfer.

Full guide: /transaction-monitoring/travel-rule#testing-without-network-credentials.`

\</pre>



      
      

Paste into



## OpenAPI

````yaml POST /v3/travel-rule/test-vasp/inbound/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: Identity verification API. Authenticate with x-api-key header.
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/travel-rule/test-vasp/inbound/:
    post:
      tags:
        - Travel Rule
      summary: Trigger an inbound transfer from the Didit Test VASP (sandbox)
      description: >-
        Sandbox applications only. The Didit Test VASP sends your application an
        inbound Travel Rule transfer, so you can exercise the receiving side of
        an exchange end to end before going live. The transfer is booked and
        decided by the same logic a real inbound transfer from a network runs
        against your wallet address book, so the inbox, the decision and the
        wallet ownership flow behave as they do live. Nothing leaves Didit. A
        live application receives 400. Send the same `reference` again to get
        the transfer the first call booked instead of a second one.
      operationId: triggerTravelRuleTestVaspInbound
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TravelRuleTestVaspInboundRequest'
            example:
              beneficiary_wallet_address: 0xYourSandboxWallet
              scenario: accept
              amount: '1'
              reference: demo-001
      responses:
        '201':
          description: >-
            The inbound transfer was booked and decided. A repeat with the same
            `reference` returns the same body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TravelRuleTestVaspInboundResponse'
        '400':
          description: >-
            Invalid body, an unknown or unsupported `scenario`, or the
            application is a live application.
          content:
            application/json:
              schema:
                type: object
        '409':
          description: >-
            The transfer could not be booked, for example because Travel Rule is
            not enabled for the application.
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: >-
            curl -X POST
            https://verification.didit.me/v3/travel-rule/test-vasp/inbound/ \
              -H 'x-api-key: YOUR_SANDBOX_API_KEY' -H 'Content-Type: application/json' \
              -d '{"beneficiary_wallet_address":"0xYourSandboxWallet","scenario":"accept","reference":"demo-001"}'
components:
  schemas:
    TravelRuleTestVaspInboundRequest:
      type: object
      required:
        - beneficiary_wallet_address
      properties:
        beneficiary_wallet_address:
          type: string
          description: >-
            The destination wallet address. The Didit Test VASP sends to it,
            matched against your wallet address book on the chain of the asset.
            A wallet with no matching entry is accepted and the inbound
            transaction is booked ON_HOLD.
        scenario:
          type: string
          enum:
            - accept
            - name_mismatch
          default: accept
          description: >-
            What the Didit Test VASP declares the beneficiary to be. `accept`
            declares the holder's own name; `name_mismatch` declares a name no
            holder agrees with. The decision itself is always yours.
        chain:
          type: string
          default: ETH
          description: Chain of the asset.
        amount:
          type: string
          default: '1'
          description: Amount as a decimal string.
        currency:
          type: string
          default: ETH
          description: Asset code.
        reference:
          type: string
          description: >-
            Optional idempotency key. A repeat with the same value returns the
            transfer the first call booked.
    TravelRuleTestVaspInboundResponse:
      type: object
      properties:
        transaction_id:
          type: string
          format: uuid
          description: Didit transaction UUID of the inbound transfer.
        txn_id:
          type: string
          description: Didit-generated txn_id.
        scenario:
          type: string
          description: The scenario that ran.
        travel_rule_status:
          type: string
          description: The status your application's own decision resolved to.
        detail:
          type: string
          description: Why the transfer resolved to that status.
        test_vasp:
          type: boolean
          description: 'Always true: the sender was the Didit Test VASP.'
        travel_rule:
          $ref: '#/components/schemas/TravelRuleTransferDetail'
    TravelRuleTransferDetail:
      type: object
      description: >-
        Full transfer object returned by the ownership-confirmation and
        finish/cancel endpoints. While an inbound transfer's wallet ownership is
        unconfirmed, the counterparty's `originator_data` and `beneficiary_data`
        come back masked (the first letter of each word is kept; the wallet,
        chain and VASP routing stay readable) and `data_masked` is 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: >-
            The rail the transfer was routed over, or null when no rail was
            selected (for example below the threshold, a self-hosted
            counterparty wallet, an after-deposit registration, or no reachable
            counterparty). INTERNAL means both sides are Didit applications;
            EMAIL means the counterparty was reached by an emailed pickup link.
            TEST_VASP means the Didit Test VASP answered a sandbox application's
            transfer. Over GTR, VERIFYVASP and SYGNA, Didit reads the
            counterparty's answer from the network's response or by polling it
            every 5 minutes. TRUST only sends, so a TRUST transfer stays
            AWAITING_COUNTERPARTY until it expires. A network rail is used only
            when you have connected your own membership for that network. It is
            chosen after the transaction create returns, so it is null in that
            response.
        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: >-
                  The name comparison this entry decided, next to `detail`.
                  Absent on entries that compared no name.
              reason:
                type: string
                description: >-
                  Present only on the entry of a transition a failed delivery
                  caused: `email_undeliverable` or `delivery_failed`, the value
                  the transfer's `reason` reports.
        counterparty_vasp:
          type: object
          nullable: true
          properties:
            name:
              type: string
            lei:
              type: string
            dd_score:
              type: integer
              description: >-
                Due-diligence score from 0 to 100, where higher is better. Same
                scale as in the VASP directory.
            dd_score_breakdown:
              type: object
              description: >-
                Per-component contributions to dd_score, one object per
                component as in the VASP directory (jurisdiction, verification,
                protocol, lei, history, essentials, responsiveness), each
                {points, max, reason, detail}. {} until the counterparty has
                been assessed.
              additionalProperties:
                type: object
                properties:
                  points:
                    type: number
                    description: Points awarded for this component.
                  max:
                    type: integer
                    description: Maximum points this component can award.
                  reason:
                    type: string
                    description: Machine-readable code of the component's verdict.
                  detail:
                    type: string
                    description: Human-readable reason for the awarded points.
            dd_assessed_at:
              type: string
              format: date-time
              nullable: true
              description: >-
                When the due-diligence assessment last ran. Null until the
                counterparty has been assessed.
        originator_data:
          type: object
          description: >-
            Originator party. For an inbound transfer the counterparty's values
            are masked until ownership is confirmed.
        beneficiary_data:
          type: object
          description: >-
            Beneficiary party. For an inbound transfer the counterparty's values
            are masked until ownership is confirmed.
        name_match:
          allOf:
            - $ref: '#/components/schemas/TravelRuleNameMatch'
          nullable: true
          description: >-
            The name comparison that decided the transfer, or null until one
            ran. While the parties are masked, and on the other customer's copy
            of an INTERNAL exchange, `transfer_name`, `compared_name`,
            `matched_names` and `mismatched_names` are hidden. `score` and
            `matched` can disagree: `matched` follows the strictness, `score` is
            the similarity of the two full names.
        data_match:
          $ref: '#/components/schemas/TravelRuleDataMatch'
        mismatched_fields:
          type: array
          items:
            type: string
          description: >-
            Shortcut for `data_match.mismatched_fields`. Empty when nothing
            differs.
        data_unmasked:
          $ref: '#/components/schemas/TravelRuleDataUnmasked'
        data_masked:
          type: boolean
          description: >-
            True while the counterparty's personal data is masked in this
            response.
        created_at:
          type: string
          format: date-time
        delivery:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/TravelRuleDelivery'
          description: >-
            Where the latest message this transfer owes the other side stands.
            Null when the transfer never owed one (for example below
            `threshold_amount`, a declared self-hosted wallet, or a sunrise
            registration).
        discovery:
          type: array
          description: >-
            How Didit looked for the counterparty, one entry per step that ran.
            Empty when no discovery ran, for example on an inbound transfer.
          items:
            $ref: '#/components/schemas/TravelRuleDiscoveryStep'
        reason:
          type: string
          description: >-
            Why a `COUNTERPARTY_VASP_NOT_FOUND` or
            `COUNTERPARTY_VASP_NOT_REACHABLE` transfer is stuck; `""` for any
            other status. A failed delivery decides it first, on
            `COUNTERPARTY_VASP_NOT_REACHABLE` only: `email_undeliverable` (the
            mail provider refused the compliance email and no address is left to
            try: when it was sent, on a reminder, or as a permanent bounce
            reported later) or `delivery_failed` (the rail that was delivering
            failed for good: a network rail refused the message or ran out of
            retries, a `TRP` identity host did not answer, or the counterparty's
            `TRP` host did not accept the inquiry). Otherwise the `discovery`
            trace decides it: `awaiting_end_user` (no step named a counterparty
            Didit can reach), `directory_match_no_route` (a step named a
            directory VASP that has no route),
            `picked_member_without_proven_wallet` (the end user picked a Didit
            customer that has not proven control of the wallet), or
            `no_directory_match` when the trace gives no other reason. A resend
            moves the transfer on, so the reason clears. See [Why a transfer is
            stuck](/transaction-monitoring/travel-rule#why-a-transfer-is-stuck).
        next_actions:
          type: array
          description: >-
            What moves the transfer on; `[]` for any status but
            `COUNTERPARTY_VASP_NOT_FOUND` or `COUNTERPARTY_VASP_NOT_REACHABLE`.
            `email_undeliverable` offers `update_compliance_email`, then
            `resend`. `delivery_failed` offers `resend`. A discovery reason
            offers `select_counterparty_vasp`, `declare_self_hosted`,
            `add_vasp_hint` and `resend`.
          items:
            $ref: '#/components/schemas/TravelRuleNextAction'
        chain_details:
          $ref: '#/components/schemas/TravelRuleChainDetails'
    TravelRuleNameMatch:
      type: object
      nullable: true
      description: >-
        The name comparison that decided the transfer, or null until one ran.
        While the parties are masked, and on the other customer's copy of an
        INTERNAL exchange, `transfer_name`, `compared_name`, `matched_names` and
        `mismatched_names` are hidden. `score` and `matched` can disagree:
        `matched` follows the strictness, `score` is the similarity of the two
        full names.
      properties:
        score:
          type: integer
          minimum: 0
          maximum: 100
          description: >-
            Similarity of the two full names, 0 to 100. 0 when either name is
            blank.
        matched:
          type: boolean
          description: >-
            Whether the names satisfy `strictness`. The transfer's outcome
            follows `data_match`, which compares every field, so a transfer can
            be COUNTERPARTY_MISMATCHED_DATA while this is true.
        method:
          type: string
          enum:
            - none
            - exact_token
            - token_subset
            - token_containment
            - sequence_ratio
          description: >-
            How `matched` was decided: none (`NONE`), exact_token (`STRICT`),
            token_subset (`DEFAULT`), token_containment (`CONTAINS`) or
            sequence_ratio (`FUZZY`).
        strictness:
          type: string
          enum:
            - NONE
            - STRICT
            - CONTAINS
            - DEFAULT
            - FUZZY
        compared_with:
          type: string
          enum:
            - wallet_holder
            - counterparty_vasp
          description: >-
            wallet_holder: the holder recorded for the wallet.
            counterparty_vasp: the name the counterparty answered on the email
            response page, or the Didit Test VASP's answer in sandbox.
        transfer_name:
          type: string
          description: The name on the transfer.
        compared_name:
          type: string
          description: The name it was compared with.
        matched_names:
          type: array
          items:
            type: string
          description: Words of `transfer_name` found in `compared_name`.
        mismatched_names:
          type: array
          items:
            type: string
          description: >-
            Words of `transfer_name` missing from `compared_name`, then words of
            `compared_name` missing from `transfer_name`.
    TravelRuleDataMatch:
      type: object
      nullable: true
      description: >-
        Field-by-field comparison of the transfer's party data with what the
        other side knows about the wallet holder. It names fields and results,
        never values, so it stays readable while the counterparty's data is
        masked. Null until a comparison ran.
      properties:
        matched:
          type: boolean
          description: True when no compared field differs.
        mismatched_fields:
          type: array
          items:
            type: string
            enum:
              - name
              - date_of_birth
              - address
              - account
          description: The fields that differ.
        fields:
          type: object
          description: >-
            One entry per field compared for the party's entity type (`name`,
            `date_of_birth`, `address`, `account`; a company has no
            `date_of_birth`).
          additionalProperties:
            type: object
            properties:
              result:
                type: string
                enum:
                  - matched
                  - mismatched
                  - not_compared
                description: >-
                  `not_compared` when the rule is `NONE` or either side has no
                  value for the field.
              strictness:
                type: string
                enum:
                  - NONE
                  - STRICT
                  - CONTAINS
                  - DEFAULT
                  - FUZZY
    TravelRuleDataUnmasked:
      type: object
      nullable: true
      description: >-
        Audit record of the moment the counterparty's data was unmasked. Null
        while the data is still masked, and for outbound transfers.
      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: >-
            What confirmed ownership: ownership_confirmed (your confirmation
            through the console or the API), wallet_proof (a wallet proof in the
            widget, or an INTERNAL inbound transfer, set when it is created),
            address_book_match (a verified address-book wallet),
            own_verified_wallet (your user's own verified wallet),
            inquiry_approved (your approval of an inbound TRP inquiry or a GTR
            or Sygna message), known_payment_method (a wallet your user already
            paid with) or travel_address (the per-wallet travel address named
            the wallet).
        actor:
          type: string
          description: >-
            Who confirmed it: the console user's email or the API key's label.
            Blank for an automatic decision.
    TravelRuleDelivery:
      type: object
      description: >-
        Where the latest message the transfer owes the other side stands. Didit
        contacts the counterparty after the request that created or changed the
        transfer has returned, so this object says whether that message got
        through: queued, being sent, waiting to be retried after an error,
        delivered, or failed. A failure the network may still recover from (no
        answer in time, a failed connection, HTTP `408`, `429` or `5xx`) is
        tried again after 30 seconds, 2 minutes, 10 minutes, 30 minutes and 1
        hour. When a first message (`kind: SEND`) fails for good, because the
        network refused it or the sixth attempt failed too, the transfer moves
        to `COUNTERPARTY_VASP_NOT_REACHABLE` with `last_error` in its
        `timeline`; any other message that fails for good is noted in the
        `timeline`. The transfer's `status` stays the source of truth for the
        exchange itself.
      required:
        - kind
        - status
        - rail
        - attempts
        - last_error
        - next_attempt_at
        - delivered_at
      properties:
        kind:
          type: string
          enum:
            - SEND
            - ANSWER
            - TXID
            - CANCEL
            - POLL
          description: >-
            What the message carries. `SEND`: the transfer's first message to
            the counterparty (outbound; the rail is chosen when it is sent).
            `ANSWER`: your accept or decline, owed to the network that asked
            (inbound). `TXID`: the on-chain transaction hash, after you finish
            the transfer. `CANCEL`: the cancellation, after you cancel it.
            `POLL`: a status query to a network that offers one, repeated every
            5 minutes while the transfer waits on the counterparty.
        status:
          type: string
          enum:
            - QUEUED
            - SENDING
            - RETRYING
            - DELIVERED
            - FAILED
          description: >-
            `QUEUED`: waiting to be sent. `SENDING`: an attempt is running.
            `RETRYING`: an attempt failed and the next one runs at
            `next_attempt_at`. `DELIVERED`: the other side took the message.
            `FAILED`: the other side refused it, or the last attempt failed.
        rail:
          type: string
          enum:
            - INTERNAL
            - TRP
            - GTR
            - TRUST
            - VERIFYVASP
            - SYGNA
            - EMAIL
            - ''
          description: >-
            The rail that carries the message. Empty until Didit has chosen one
            for a first message.
        attempts:
          type: integer
          minimum: 0
          description: >-
            Attempts made so far for this message. A message that is not a
            status poll is attempted at most 6 times.
        last_error:
          type: string
          description: >-
            The kind of failure the last attempt hit, `""` when none did: for
            example `email undeliverable`, `trp identity endpoint unreachable`
            or `trp transfer inquiry delivery failed`. It never carries the
            counterparty's own answer, which stays on the transfer's `timeline`.

            When GTR answers with an error, its own status code and message are
            included. Response bodies are never included.
          example: email undeliverable
        next_attempt_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            When the next attempt runs while the message is `QUEUED` or
            `RETRYING`.
        delivered_at:
          type: string
          format: date-time
          nullable: true
          description: When the other side took the message.
    TravelRuleDiscoveryStep:
      type: object
      description: >-
        One step of the counterparty discovery Didit ran for an outbound
        transfer, in the order it ran them. The first step that names a VASP
        with a route ends the chain.
      properties:
        step:
          type: string
          enum:
            - internal_address_book
            - wallet_attribution
            - network_lookup
            - customer_hint
            - end_user
          description: >-
            `internal_address_book`: another Didit customer that proved control
            of the destination wallet. `wallet_attribution`: the wallet's
            blockchain analytics attribution. `network_lookup`: a network that
            can say which VASP holds the address. `customer_hint`: the VASP
            name, LEI or jurisdiction you sent in `beneficiary_data`.
            `end_user`: the counterparty the end user (or you) picked, or the
            request to pick one.
        outcome:
          type: string
          enum:
            - match
            - miss
            - skipped
          description: >-
            `match`: the step named a counterparty. `miss`: it ran and found
            none. `skipped`: it could not run, and `reason` says why.
        reason:
          type: string
          description: >-
            Machine-readable reason, `""` on a match:
            `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` or `picked_member_without_proven_wallet`.
        vasp:
          type: string
          format: uuid
          nullable: true
          description: The directory VASP the step named, when it named one.
        rail:
          type: string
          nullable: true
          description: The rail that reaches that counterparty, when the step found one.
        at:
          type: string
          format: date-time
    TravelRuleNextAction:
      type: object
      description: >-
        One thing that moves a `COUNTERPARTY_VASP_NOT_FOUND` or
        `COUNTERPARTY_VASP_NOT_REACHABLE` transfer on. See [Why a transfer is
        stuck](/transaction-monitoring/travel-rule#why-a-transfer-is-stuck).
      properties:
        action:
          type: string
          enum:
            - select_counterparty_vasp
            - declare_self_hosted
            - add_vasp_hint
            - update_compliance_email
            - resend
          description: >-
            `select_counterparty_vasp`: the end user picks the destination VASP
            in the wallet-ownership widget. `declare_self_hosted`: the end user
            declares the wallet self-hosted in the widget. `add_vasp_hint`: tell
            Didit who the counterparty is, with a VASP name, LEI or travel
            address (for example a `travel_address` on the destination wallet's
            address-book entry), then resend. `update_compliance_email` and
            `resend` are `action` values of `PATCH
            /v3/transactions/{transaction_id}/travel-rule/`: give the
            counterparty's compliance email again, and re-run routing.
        url:
          type: string
          format: uri
          description: >-
            The wallet-ownership widget link, on `select_counterparty_vasp` and
            `declare_self_hosted` while the transfer has an open widget session.
      required:
        - action
    TravelRuleChainDetails:
      type: object
      description: >-
        How the transfer's chain names its two wallets, when that is more than
        one address paying another. Empty (`{}`) for an account-chain transfer
        (EVM, Solana, Tron), where the two addresses are the wallets. Matching,
        routing and the address book read the wallets from here first.
      properties:
        chain:
          type: string
          description: >-
            Canonical chain, e.g. `BTC`, `XRP`, or `LIGHTNING` for a Lightning
            transfer.
        shape:
          type: string
          enum:
            - utxo
            - memo
            - lightning
        originator:
          $ref: '#/components/schemas/TravelRuleChainSide'
        beneficiary:
          $ref: '#/components/schemas/TravelRuleChainSide'
        utxo:
          type: object
          description: >-
            On a UTXO transfer: the inputs and outputs as stored (amounts as
            decimal strings) and which outputs Didit read as what.
          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: Outputs that pay an input address back.
            beneficiary_output_index:
              type: integer
              nullable: true
              description: >-
                The output that pays the beneficiary; null when none could be
                told apart.
        lightning:
          type: object
          description: >-
            On a Lightning transfer: what the payment request says. Always
            `kind` (`bolt11`, `bolt12_offer`, `bolt12_invoice`,
            `bolt12_invoice_request`, `lnurl`, `lightning_address`, `node_id` or
            `unknown`); a BOLT11 invoice adds `network`, `payee_node_id`,
            `payment_hash`, `amount_msat`, `created_at` and `expires_at`; a
            BOLT12 string `blinded_paths` and `payee_node_id`; an LNURL or a
            Lightning Address its `domain`. Nothing is resolved over the
            network: the request is decoded only.
          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: >-
            UTXO inconsistencies worth a look: the declared originator is not an
            input, the declared beneficiary is not an output, no single
            beneficiary output could be told apart, or the beneficiary output
            pays a different amount than the transaction states.
        not_applicable_reason:
          type: string
          enum:
            - LIGHTNING_NO_PAYEE_IDENTIFIER
            - LIGHTNING_BOLT12_BLINDED_PAYEE
            - LIGHTNING_LNURL_NAMES_NO_PAYEE
          description: >-
            On an outbound Lightning transfer whose payment request names no
            payee: why the transfer is `NOT_APPLICABLE`.
            `LIGHTNING_NO_PAYEE_IDENTIFIER` (the request names no payee node, or
            could not be decoded), `LIGHTNING_BOLT12_BLINDED_PAYEE` (the offer
            hides its payee behind blinded paths),
            `LIGHTNING_LNURL_NAMES_NO_PAYEE` (an LNURL names a service, not a
            payee). The same code opens the transfer's last `timeline` entry.
    TravelRuleChainSide:
      type: object
      description: One side's wallet as Didit resolved it from the chain data.
      properties:
        address:
          type: string
          description: >-
            The wallet. On a memo network the classic address (an XRP X-address
            is split into its classic address and its tag); on Lightning the
            payee node id or Lightning Address.
        memo:
          type: string
          description: >-
            The destination tag or memo that is part of the wallet; `""` for
            none.
        source:
          type: string
          enum:
            - declared
            - x_address
            - largest_input
            - only_non_change_output
            - amount_match
            - invoice_payee
            - updated
          description: >-
            Where the wallet came from: `declared` (your request), `x_address`
            (split from an XRP X-address), `largest_input` (the UTXO input
            address that contributed the most), `only_non_change_output` (the
            only UTXO output that is not change), `amount_match` (the one UTXO
            output paying the transfer amount), `invoice_payee` (the payee a
            Lightning payment request names), `updated` (set later with `action:
            update_originator_wallet`).
    TravelRuleUtxoEntry:
      type: object
      description: One input or output of a UTXO transaction, as the chain recorded it.
      required:
        - address
      properties:
        address:
          type: string
          maxLength: 128
        amount:
          type: string
          nullable: true
          description: Decimal string in the coin's own unit (BTC, not satoshis). Optional.
          example: '0.0125'
        txid:
          type: string
          maxLength: 128
          description: Optional. The transaction an input spends.
        vout:
          type: integer
          nullable: true
          minimum: 0
          description: Optional. The output index an input spends.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Your application's API key, from Developers -> API keys in the Business
        Console. The primary key has full access. A named key can be scoped:
        none, read or write per resource, limited to some workflows or to
        approved sessions, to a list of IP addresses, and to an expiry date. 401
        means the key is missing, wrong, revoked or expired; 403 means the key
        has no access to this resource or action, or the request came from an
        address outside its IP list; 404 on a session route means the session is
        outside the key's workflows or statuses. A key without media access
        receives image, video and PDF URLs as null, and a key without sessions
        write receives session links and tokens as null. See
        https://docs.didit.me/console/api-keys.

````

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