
# Crypto operations

Open **Risk Intelligence → Fraud Monitoring → Transactions**. Use **Crypto transfers**
for assessed transactions, **Unmatched deposits** for observations that need matching,
**Crypto Provider Directory** for sourced crypto provider records, and **Address book** for saved
destinations. Existing transaction URLs and decisions are unchanged.

## Connect in minutes

Select **Integration guide**, choose your use case and stack, then copy the request or
the Coding agent prompt. You can use cURL, Node.js, Python or Go without installing an SDK.
The guide checks that your Sandbox request arrived and links to its canonical record.
It never sends a Live request or places secrets in a browser URL.

The five-minute target starts with an available Sandbox secret key and ends with a first
decision and a signature-verified sample in your own webhook receiver. Live access still
requires business approval, permissions, configured controls and production testing.

Machine-readable integration resources on the API origin:

- `/openapi.json`: request and response contracts.
- `/integration/examples?useCase=crypto`: generated requests and a Node.js webhook verifier.
- `/llms.txt` and `/llms-full.txt`: coding-agent instructions.
- `/.well-known/myaza-trust.json`: API and documentation discovery.

Examples support `payments`, `crypto`, `account`, `custom` and `deposits`. Use the `apiBase`
returned by the example. Custom events use `/api/identity`; the other examples use `/api/v1`.
Existing SDK transaction methods still work. The new crypto record endpoints are HTTP APIs;
do not assume your installed SDK already has matching convenience methods.

## What each record means

| Record | Meaning | Does not mean |
|---|---|---|
| Crypto transfer | A canonical transaction assessed by your existing controls | Myaza moved or released funds |
| Deposit observation | Your backend reported an inbound chain output | A customer is matched or a decision was made |
| Crypto provider evidence | Platform-reviewed, sourced identity and registration information | A compliance guarantee or active Travel Rule connection |
| Approved address | Your organisation approved the saved destination | Ownership was verified or standalone screening ran |

The network catalogue validates supported address syntax. It does not enable an automatic
chain feed, verify checksums or prove control of a wallet. Never silently round asset amounts
beyond the supported eight decimal places.

## Check a transfer's clearance

Open a crypto transaction and use **Check transfer** under **Transfer clearance**.
The result keeps the risk decision, information review, secure exchange and funds
movement separate. **On hold** means do not release funds. **Cancel clearance** stops
that clearance record; it does not reverse a blockchain transaction. Past checks remain
available in the history. Team members with read-only access can view and reload results.

Country coverage and exchange connections are still being qualified. **No current policy
is enabled for live clearance.** Passing information checks, a risk-only **Allow**, a
saved crypto provider or a matched deposit is not permission to release funds. Myaza Trust
does not move funds or automatically block actions on your platform.

From your backend, use the additive endpoints:

- `GET /api/v1/transactions/{id}/travel-rule/transfer` reads current clearance, or
  `{ "transfer": null }` when no check has been started.
- `POST /api/v1/transactions/{id}/travel-rule/transfer` starts or refreshes a check.
  Send `Idempotency-Key` and `{ "action": "refresh" }`. For an existing record, include
  its `expectedRevision`. Send `action: "cancel"` with that revision to cancel it.

Retry an uncertain request with the **same key and unchanged body**. A replay identifies
the original command revision but returns the current safe transfer state. Reload after
a revision conflict. Initial expiry defaults to one hour and cannot be extended by a
refresh. Cancelled and expired records cannot be reopened. These commands do not charge
credit, contact another institution or move funds.

Your execution backend must retain its hold when clearance is missing, unavailable,
expired or `canRelease` is false. This API is not yet a signed, single-use execution
authorisation; keep real transfers disabled until the complete integration is qualified.

## Manage crypto networks

Platform admins can select **Manage networks** in the Crypto Provider Directory, Address
book or Unmatched deposits. Add a name, stable network code, address format and audit reason.
New entries become available in crypto record forms and Travel Rule policy network pickers.
The network code and address format cannot change after creation. Disable an entry to stop
new records; existing records, exact retries and history remain available. Concurrent edits
require reloading the latest catalogue before saving again.

`GET /api/v1/crypto/catalogue` returns active `networks` plus `networkOptions`, including
disabled entries for historical display. Only authorised platform admins can change the
catalogue. This does not add a supported funding rail: credit
top-ups still use the receiving wallets separately configured by platform finance.

## Report and match a deposit

Send `POST /api/v1/crypto/deposits` from your backend with a secret key and an
`Idempotency-Key` header. The minimal body is available in **Integration guide → Deposit
feed**. Include `externalDepositId`, `network`, `transactionHash`, `outputIndex`,
`destination`, decimal-string `amount`, `currency`, `confirmations` and ISO `observedAt`.
Use a stable output index, such as the transaction's log index for a token transfer.

The observation appears under **Unmatched deposits**. Your team can:

- **Match customer**: select an existing customer and record a reason. Myaza runs the
  existing transaction assessment and pricing, then links the observation.
- **Link existing transaction**: choose an already assessed inbound crypto transaction.
  Amount, currency, network, chain hash, output and destination must all match. No second
  assessment or charge is created.
- **Add to address book**: save the retained destination without exposing its full value
  in the browser. It starts as a claimed address awaiting review.
- **Needs review** or **Ignored**: record the reason. Observations remain in history.

For API integration, use `POST /api/v1/crypto/deposits/{id}/assessment` with `customerId`,
current `version` and `reason`, or `/matches` with `transactionId`, `version` and `reason`.
Use the same idempotency key and unchanged body on retries. Once assessment starts, the
selected customer is fixed. A timeout can be resumed without creating a second charge.

Update confirmations or report a reorganisation with `PATCH /api/v1/crypto/deposits/{id}`.
A reorganisation does not erase the historical assessment or silently unmatch the deposit.
It emits an event for your backend to handle. Never treat a matched record as fund release.

## Crypto provider reviews and address book

Platform reviewers add crypto provider evidence with a source URL, jurisdiction and a concise
review summary. Every revision is retained. An empty directory means no records have been
curated; the product does not invent crypto providers or licences.

Your team's **Approved**, **Watchlist** and **Avoid** review is scoped to its organisation
and environment. It does not edit global evidence or automatically change transaction rules.
Use Rules & Policies for enforcement. Travel Rule is shown as **Not configured** until a
real connection is supported and configured.

Saved addresses are encrypted at rest and masked in responses. Approval, suspension and
archiving require a reason and the current record version. Address approval is distinct
from ownership verification and transaction screening.

## Address tools

### Find the wallet's crypto provider

When your organisation has exchange-network discovery enabled, open a saved wallet
and use **Crypto provider → Find crypto provider**. Enter the asset, such as USDT. Myaza
asks the connected network which institution recognises that wallet. Results appear
in the same address details, beside wallet screening and control checks.

A **Network match** is exchange-reported evidence, not ownership verification or
transfer approval. **No crypto provider confirmed** does not mean a wallet is self-hosted.
Multiple matches need clarification. The network does not reach every exchange and
does not provide blockchain risk scores, address categories or transaction history.
Discovery targets participating institutions' customer deposit wallets, not their cold wallets.
Myaza manages the network credentials; customers do not enter signing keys here.

From a backend, use the existing secret-key crypto API:

```http
POST /api/v1/crypto/addresses/{id}/discovery
Content-Type: application/json

{
  "requestId": "1d526c54-e8ed-4b2f-b034-3a5ea370f9c2",
  "version": 1,
  "currency": "USDT"
}
```

Use a fresh UUID for a new lookup and the address's current version. Save the UUID
before sending. Poll `GET /api/v1/crypto/addresses/{id}/discovery/{requestId}` at
least 12 seconds apart, including after a timeout. An exact same-body retry never
reposts the vendor lookup. Do not create another request ID to recover uncertainty.
The dashboard's **Check again** polls the original request.

Results are `pending`, `matched`, `unknown` or `ambiguous`. A matched result can
include `institutionId`, `institutionName`, `legalName` and `checkedAt`. Requests
are scoped to the original organisation/environment, address and account-binding
version and expire after one hour. Configuration or address changes can invalidate
the result. No private address or signing key is returned.

`GET /api/v1/crypto/network/status` lists locally configured discovery capabilities
and enabled network codes. `GET /api/v1/crypto/network/institutions` returns the
network directory. These are distinct from Myaza's reviewed crypto provider records.
In **Crypto providers**, select **Browse network** to search those institutions by
company or country. Browsing does not add companies to the reviewed directory or
activate connections.
The CodeVASP connector currently supplies discovery; its `transferExchange` capability
is false. Existing TRP connections and their activation/release checks are unchanged.

### Screen, edit or verify control

Open a saved address to edit its label or linked customer or crypto provider, run wallet screening,
or prove control. The wallet and network cannot be edited; save a new destination instead.
Relinking a customer or crypto provider returns the address to review and clears its control proof.

- **Screen address** uses the existing wallet-screening price and assessment engine.
  Sandbox results are labelled. Waiting for credit, running, failure and a completed
  decision are different states. Screening never approves the address for your team.
- **Verify control** creates a message that expires in ten minutes. Ask the wallet holder
  to sign it and paste back the signature. Ethereum, Polygon, Arbitrum and Base personal
  wallets are supported; smart-contract wallets are not. No funds, keys or recovery phrases
  are requested. A valid signature proves key control at that time, not legal ownership.
- **Reveal address** requires both management access and `crypto_addresses:reveal`.
  Record a reason. The address hides after 30 seconds or when the page loses visibility;
  the audit trail records access without retaining the full address.

The matching API actions live at `/api/v1/crypto/addresses/{id}/metadata`, `/screening`,
`/control-challenge`, `/control-proof` and `/reveal`. Read the exact request schema before
writing an integration. Each write requires `Idempotency-Key`; retry unchanged input with
the same key after a timeout. A control proof returns the updated record version.

## Directory and connections

Search directory names, LEIs and registration references. Filter by jurisdiction, review
status, registration evidence or network. Filters are applied before pagination. An
organisation review does not change the platform's sourced record or endorse a crypto provider.

Select **Set up Travel Rule** from the transaction workspace to choose your company,
manage exchange connections, open transfer rules and configure result notifications.
The same setup is available under **Manage controls → Travel Rule setup**.
Use **Advanced** for deposit-feed diagnostics, delivery history and historical wallet
reviews. Sandbox and Live profiles stay separate. A company selection does not establish
a connection; a successful HTTP delivery does not prove signature verification.
Live exchange requires an approved, configured institution connection.

In **Crypto providers**, search by company name, LEI or registration reference.
Use **Filters** to narrow the directory. Open a company to see its profile, expand
**Company evidence** for source records, or record your team's assessment in the
review section. Directory review, team review and connection status are separate.

Unmatched deposits show current totals for deposits to match, matched deposits and addresses
to review. These are current queues, not time-series or financial-volume analytics.

## Coding-agent documentation server

For teams with the Core repository checked out, a local, read-only MCP server supplies
OpenAPI contracts and the same copy-ready examples. It cannot call your API, read keys,
access files, run commands or change customer data. Install the repository dependencies
using its pinned Node version, then configure your MCP client to run:

```json
{
  "mcpServers": {
    "myaza-trust-integration": {
      "command": "node",
      "args": ["--import", "/absolute/path/to/myaza-kyc-core/node_modules/tsx/dist/loader.mjs", "/absolute/path/to/myaza-kyc-core/src/integration-mcp.ts"]
    }
  }
}
```

Replace the paths with your checkout. No environment secrets are required. Available tools
are `integration_example` and `api_schema`; `myaza://integration/openapi` is the contract
resource. Alternatively, run `pnpm mcp:integration` from Core. Teams without the repository
can use the public OpenAPI and llms resources above; no hosted MCP service is advertised.

## Webhooks and safe retries

Subscribe to `crypto.deposit.unmatched`, `crypto.deposit.matched`,
`crypto.deposit.reorged`, `crypto.address.approved` and `crypto.address.suspended` in the
existing webhook settings. Payloads contain masked projections, never full wallet addresses.

Use the existing webhook simulator and the guide's **Copy Node.js verifier** action.
Verify `X-Myaza-Signature-V2` against the exact raw request bytes. Check the timestamp,
accept a valid signature from either secret during rotation, and persist a durable inbox
keyed by event `id` before acknowledging delivery. A retry may have a different `deliveryId`.
Reject tampered bodies, invalid signatures and expired timestamps. A `2xx` alone does not
prove signature verification.

All crypto writes require an idempotency key. Reusing a key with different input returns
`409`; stale review versions also return `409`. Refresh the record, explain the new decision,
and use a new key only for a genuinely new operation. An error is never approval.

Lists use `page` and `pageSize` (maximum 100). Detail evidence uses `historyPage`, 25 records
per page, with a total count. Use the page controls to read older evidence.

Read permission is `fraud_prevention:read`; review actions require
`fraud_prevention:manage`. Crypto provider curation is platform-owner only with
`platform.providers:write`. Production API calls keep the existing secret-key, product
access and business-approval gates.

## Enforcing decisions in your app

Myaza assesses and notifies. Your backend decides whether to stop a payment, restrict an
account, request another check or send a case to your team. A **Block** badge in Myaza does
not freeze the customer's account in another application.

| What you monitor | Results to subscribe to | Your application handles |
|---|---|---|
| Verification | Verification results and `risk.decision.changed` when risk controls apply | Finish onboarding, request review or refuse access using the final decision |
| Screening | `screening.match`, `screening.completed`, `screening.adjudicated` and `risk.decision.changed` | Hold a potential match for review; use the resolved decision, not the match alone |
| Transactions and account activity | `fraud.transaction.assessed`, `fraud.activity.assessed`, `fraud.decision.changed` | Allow, hold or block the particular action |
| Custom events | `event.flagged`, applicable risk decision changes and alerts | Apply the action your published policy requires |
| Device reuse or linked accounts | `risk.signal.created`, `risk.decision.changed`, `alert.created` | Review the evidence or request another check; a shared device alone is not proof of fraud |

Use `externalUserId` where provided to map the entity to your customer, and the transaction
or activity reference for an individual action. Some events have different subject shapes;
follow their documented payloads instead of assuming one shared field location.

Before releasing a payment, evaluate the latest decision in your backend. Keep pending,
failed or unavailable checks on hold according to your approved operating policy. For
crypto, completed information validation is **not** confirmation that a counterparty
received the Travel Rule information. Do not release funds based on that state alone.

Verify signatures, persist each event ID once and acknowledge only after durable receipt.
Webhooks can be retried or arrive out of order: fetch the latest record before applying a
delayed update. Test allowed, review, blocked, pending and failed outcomes, replayed events,
timeouts and manual decision changes before Live use.
