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

# Confirm or Deny Wallet Ownership

> Called by the beneficiary's application when its INTERNAL-rail transfer is UNCONFIRMED_OWNERSHIP. Confirming marks the matching wallet address book entry as ownership-verified and runs the beneficiary name match on both sides of the transfer; denying declines both sides.

export const AgentPromptAccordion = ({prompt, title = "AI Agent Integration Prompt"}) => {
  const [copied, setCopied] = React.useState(false);
  const handleCopy = e => {
    e.stopPropagation();
    if (!prompt) return;
    navigator.clipboard.writeText(prompt.trim()).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  };
  const agents = ["Claude Code", "Codex", "Cursor", "Devin", "Windsurf", "GitHub Copilot"];
  return <div className="didit-agent-card">
      {}
      <div className="didit-agent-titlebar">
        <div className="didit-agent-dots" aria-hidden="true">
          <span className="didit-agent-dot didit-agent-dot-red"></span>
          <span className="didit-agent-dot didit-agent-dot-yellow"></span>
          <span className="didit-agent-dot didit-agent-dot-green"></span>
        </div>
        <span className="didit-agent-filename">{title}</span>
        <button type="button" className={`didit-agent-copy ${copied ? "didit-agent-copy-copied" : ""}`} onClick={handleCopy} title="Copy prompt to clipboard" aria-label={copied ? "Copied!" : "Copy prompt to clipboard"}>
          {copied ? <>
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                <path d="M3 8.5l3.5 3.5L13 4" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
              <span>Copied</span>
            </> : <>
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                <rect x="5" y="5" width="9" height="9" rx="1.5" stroke="currentColor" strokeWidth="1.5" />
                <path d="M11 5V3.5A1.5 1.5 0 0 0 9.5 2h-6A1.5 1.5 0 0 0 2 3.5v6A1.5 1.5 0 0 0 3.5 11H5" stroke="currentColor" strokeWidth="1.5" />
              </svg>
              <span>Copy</span>
            </>}
        </button>
      </div>

      {}
      <pre className="didit-agent-body"><code>{prompt.trim()}</code></pre>

      {}
      <div className="didit-agent-footer">
        <span className="didit-agent-footer-label">Paste into</span>
        <div className="didit-agent-chips">
          {agents.map(name => <span key={name} className="didit-agent-chip">{name}</span>)}
        </div>
      </div>
    </div>;
};

<AgentPromptAccordion
  title="Confirm Wallet Ownership API Prompt"
  prompt={`Confirm or deny wallet ownership on a Travel Rule transfer that is waiting in UNCONFIRMED_OWNERSHIP - typically the beneficiary side of an INTERNAL-rail transfer whose wallet address book entry has not been ownership-verified yet.

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

Authentication:
Use the x-api-key header with my Didit API key. {transaction_id} is the Didit transaction uuid on YOUR (beneficiary) application.

Request body:
{"confirmed": true}   or   {"confirmed": false}

Behavior:
- confirmed: true - marks the matching wallet address book entry ownership-verified, then runs the beneficiary name match on both sides: COMPLETED on a pass, COUNTERPARTY_MISMATCHED_DATA on a fail.
- confirmed: false - moves both sides of the transfer to COUNTERPARTY_VASP_GENERAL_DECLINE.

What to read from the response:
- The full transfer object. Note: originator_data/beneficiary_data are omitted on inbound transfers until ownership_confirmed is true, to avoid leaking counterparty PII before ownership is proven.

Alternative: instead of this API call, send the end customer through the hosted wallet-ownership widget (POST /v3/travel-rule/widget-session/) and let them prove control cryptographically.

Failure modes:
- 409 - the transfer is not currently UNCONFIRMED_OWNERSHIP, or its wallet address book entry was deleted.
- 404 - unknown transaction or no Travel Rule transfer attached.

Full guide: /transaction-monitoring/travel-rule#confirming-wallet-ownership.`}
/>


## OpenAPI

````yaml POST /v3/transactions/{transaction_id}/travel-rule/ownership/
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/transactions/{transaction_id}/travel-rule/ownership/:
    post:
      tags:
        - Travel Rule
      summary: Confirm or deny wallet ownership
      description: >-
        Called by the beneficiary's application when its INTERNAL-rail transfer
        is UNCONFIRMED_OWNERSHIP. Confirming marks the matching wallet address
        book entry as ownership-verified and runs the beneficiary name match on
        both sides of the transfer; denying declines both sides.
      operationId: confirmTravelRuleOwnership
      parameters:
        - name: transaction_id
          in: path
          required: true
          description: >-
            Didit-stable transaction UUID that owns the transfer (the
            beneficiary side's transaction).
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TravelRuleOwnershipConfirmRequest'
            example:
              confirmed: true
      responses:
        '200':
          description: >-
            The updated transfer. originator_data/beneficiary_data are omitted
            until ownership_confirmed is true on an inbound transfer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TravelRuleTransferDetail'
        '409':
          description: >-
            The transfer is not currently UNCONFIRMED_OWNERSHIP, or its matching
            wallet address book entry was deleted.
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: >-
            curl -X POST
            https://verification.didit.me/v3/transactions/{transaction_id}/travel-rule/ownership/
            \
              -H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \
              -d '{"confirmed": true}'
components:
  schemas:
    TravelRuleOwnershipConfirmRequest:
      type: object
      required:
        - confirmed
      properties:
        confirmed:
          type: boolean
    TravelRuleTransferDetail:
      type: object
      description: >-
        Full transfer object returned by the ownership-confirmation and
        finish/cancel endpoints. originator_data/beneficiary_data are omitted
        while PII is masked (see description).
      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
            - EMAIL
            - null
        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
        counterparty_vasp:
          type: object
          nullable: true
          properties:
            name:
              type: string
            lei:
              type: string
            dd_score:
              type: integer
        originator_data:
          type: object
        beneficiary_data:
          type: object
        created_at:
          type: string
          format: date-time
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````