> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.6mm.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.6mm.com/_mcp/server.

# Contract Transfers & Reconciliation

This guide targets **Agent Java SDK `v0.3.0`**, Java 8+, and the tagged public contract. Examples run in a partner backend after initializing `client` in [Quick Start](/sdk/agent-sdk/java/quick-start).

## Example prerequisites

The Java snippets share these imports. Initialize `client` using Quick Start and obtain `platformUserId` from the saved binding. Example user/order IDs must be replaced with your own persisted values.

```java
import com.sixmm.agent.*;
import com.sixmm.agent.model.*;
import java.util.*;
```

## Fixed Amount Transfer

Use `transfer` for fixed amount transfers. `Direction.IN` means transferring
from the partner platform into 6MM. `Direction.OUT` means transferring from 6MM
back to the partner platform.

Use strings or `BigDecimal` for amounts. Do not use `double` or `float`.

### Transfer By `agentUserId`

```java
import com.sixmm.agent.model.Direction;
import com.sixmm.agent.model.TransferRequest;
import com.sixmm.agent.model.TransferResponse;

TransferResponse resp = client.transfer(TransferRequest.fixed(
        "AGT-ORDER-1001",
        "agent-user-001",
        Direction.IN,
        "USDT",
        "10.00"));

System.out.println(resp.orderNo);
System.out.println(resp.orderStatus);
System.out.println(resp.agentUserId);
System.out.println(resp.platformUserId);
```

### Transfer By `platformUserId`

```java
TransferResponse resp = client.transfer(TransferRequest.fixedByPlatformUserId(
        "AGT-ORDER-1002",
        "1188041528",
        Direction.OUT,
        "USDT",
        "5.00"));
```

### Provide Both IDs

If both IDs are provided, the service validates that they point to the same
bound user.

```java
TransferRequest req = TransferRequest
        .fixed("AGT-ORDER-1003", "agent-user-001", Direction.IN, "USDT", "20.00")
        .withPlatformUserId("1188041528");

TransferResponse resp = client.transfer(req);
```

Request fields:

| Field            | Type   | Required      | Description                               |
| ---------------- | ------ | ------------- | ----------------------------------------- |
| `agentOrderNo`   | string | Yes           | Globally unique partner order number      |
| `agentUserId`    | string | Conditionally | Required when `platformUserId` is absent  |
| `platformUserId` | string | Conditionally | Required when `agentUserId` is absent     |
| `direction`      | enum   | Yes           | `IN` or `OUT`                             |
| `currency`       | string | No            | Filled from `defaultCurrency` when absent |
| `amount`         | string | Yes           | Decimal amount string                     |

Response fields:

| Field            | Type   | Description                             |
| ---------------- | ------ | --------------------------------------- |
| `orderNo`        | string | Platform order number                   |
| `orderStatus`    | string | `SUCCESS`, `FAILED`, `PROCESSING`, etc. |
| `agentUserId`    | string | Partner-side user ID                    |
| `platformUserId` | string | 6MM external user ID                    |

## Order Confirmation And Idempotency

After `transfer` is called, the Agent service synchronously calls the trading
core on the main path. In most cases, the API response already contains the
synchronous trading-core result.

| Result       | Meaning                                     | Partner action                                                              |
| ------------ | ------------------------------------------- | --------------------------------------------------------------------------- |
| `SUCCESS`    | Transfer succeeded                          | Mark local order as successful                                              |
| `FAILED`     | Transfer was rejected or failed             | Save the failure reason and show it when appropriate                        |
| `PROCESSING` | Trading core timeout or network uncertainty | Do not retry with a new order number. Wait for webhook or call `queryOrder` |

Idempotency requirements:

* Use one `agentOrderNo` for one business transaction.
* If HTTP times out or the network fails, query the same `agentOrderNo` first.
* Webhooks may be retried. Deduplicate them by idempotency key.

## Transfer All Out

`transferAllOut` moves the user's withdrawable 6MM-side balance back to the
partner platform.

```java
import com.sixmm.agent.model.TransferAllOutRequest;
import com.sixmm.agent.model.TransferAllOutResponse;

TransferAllOutResponse resp = client.transferAllOut(
        TransferAllOutRequest.of("AGT-ORDER-2001", "agent-user-001", "USDT"));

System.out.println(resp.orderStatus);
System.out.println(resp.amount);
```

By `platformUserId`:

```java
TransferAllOutResponse resp = client.transferAllOut(
        TransferAllOutRequest.byPlatformUserId("AGT-ORDER-2002", "1188041528", "USDT"));
```

`amount` in the response is the actual transferred amount.

## Reverse Order

Reverse is used to compensate a successful transfer order when the backend
supports the reverse flow. Typical cases include partner local order exceptions
or manual reconciliation rollback.

```java
import com.sixmm.agent.model.ReverseOrderRequest;
import com.sixmm.agent.model.ReverseOrderResponse;

ReverseOrderResponse resp = client.reverse(ReverseOrderRequest.of(
        "AGT-ORDER-1001",
        "REV-ORDER-1001",
        "partner order rollback"));

System.out.println(resp.orderStatus);
```

Fields:

| Field            | Type   | Required | Description                          |
| ---------------- | ------ | -------- | ------------------------------------ |
| `origOrderNo`    | string | Yes      | Original transfer order number       |
| `reverseOrderNo` | string | Yes      | Globally unique reverse order number |
| `reverseReason`  | string | Yes      | Reverse reason                       |

Notes:

* Reverse is not a normal cancel operation.
* Reverse orders must also be idempotent by order number.
* After an original order is reversed, webhook may push the original order's
  `REVERSED` final state.

## Query Order

```java
import com.sixmm.agent.model.OrderQueryType;
import com.sixmm.agent.model.QueryOrderRequest;
import com.sixmm.agent.model.QueryOrderResponse;

QueryOrderResponse resp = client.queryOrder(
        QueryOrderRequest.of("AGT-ORDER-1001", OrderQueryType.TRANSFER_IN));

System.out.println(resp.status);
System.out.println(resp.failReason);
```

Supported `orderType` values:

* `TRANSFER_IN`
* `TRANSFER_OUT`

Common response fields:

| Field            | Type   | Description                 |
| ---------------- | ------ | --------------------------- |
| `orderType`      | string | Order type                  |
| `orderNo`        | string | Partner order number        |
| `status`         | string | Order status                |
| `direction`      | string | `IN` or `OUT`               |
| `transferMode`   | string | `FIXED_AMOUNT` or `ALL_OUT` |
| `currency`       | string | Currency                    |
| `amount`         | string | Amount                      |
| `agentUserId`    | string | Partner-side user ID        |
| `platformUserId` | string | 6MM external user ID        |
| `failReason`     | string | Failure reason              |
| `createdAt`      | string | Creation time               |
| `completedAt`    | string | Completion time             |

## List Orders

```java
import com.sixmm.agent.model.ListOrdersRequest;
import com.sixmm.agent.model.ListOrdersResponse;

ListOrdersRequest req = ListOrdersRequest.page(1, 20);
req.orderType = "TRANSFER_IN";
req.status = "SUCCESS";
req.startTime = "2026-06-01T00:00:00Z";
req.endTime = "2026-06-16T00:00:00Z";

ListOrdersResponse resp = client.listOrders(req);

System.out.println(resp.total);
resp.orders.forEach(order -> System.out.println(order.orderNo));
```

Pagination recommendations:

* `page` starts from 1.
* Keep `pageSize` at or below 100.
* For reconciliation jobs, page by time window and deduplicate by `orderNo`.

## Source and related guides

* [Official v0.3.0 source](https://github.com/6mm-com/agent-java-sdk/tree/54aa3c1)
* [Query overview and pagination](/sdk/agent-sdk/java/perpetual-queries)
* [Funding wallet](/sdk/agent-sdk/java/funding-wallet)
* [Upgrade guide](/sdk/agent-sdk/java/upgrade)

## Funds event callbacks

`transfer.completed` may carry `SUCCESS`, `FAILED`, or an original order update of `REVERSED`; `reverse.completed` is a reversal order terminal event. `transfer.dead` means the final state remains unconfirmed after retries and needs manual reconciliation, not a confirmed failure. The event name alone does not prove funds were credited.

Successful acknowledgement is distinct from successful funds movement: after recording a valid `targetStatus=FAILED` notification, return HTTP 2xx as well. Persist funds-event deduplication by `orderType:orderId:targetStatus` within the merchant and `environment` scope.

[Event fields and JSON examples](/sdk/agent-sdk/java/webhook-events) · [Signature verification, responses, and retries](/sdk/security/webhooks-idempotency)