Circle USYC 백서

Circle USYC

원문

bitpro가 원문에서 글자만 모은 내용이에요. 표·그림·수식은 빠지거나 깨질 수 있어요. 전체 75쪽 중 70쪽

| Parameter | Type | Notes | | - | - | - | | `page` | integer | Page number, 1-based. Defaults to 1. | | `pageSize` | integer | Results per page. Default 20, maximum 100. | | `status` | string | Filter by order status. An unknown value returns 400. | | `orderType` | string | `BURN` or `MINT`. Any other value returns 400. | | `orderId` | UUID string | Returns only the order matching this UUID. A malformed value returns 400. | | `from` | date-time string | Created-at lower bound (inclusive). | | `to` | date-time string | Created-at upper bound (inclusive). Passing `from` after `to` returns 400. | The response includes a `pagination` object alongside the `orders` array: ```json theme={null} { "data": { "orders": ["..."], "pagination": { "page": 1, "pageSize": 50, "total": 142 } } } ``` ### Step 5. Get a single order and read lineage and fill Use `GET /v1/match/orders/{id}` to fetch full detail for one order, including its lineage and fill result. ```bash theme={null} curl -X GET "https://api-sandbox.circle.com/v1/match/orders/$ORDER_ID" \ -H "Authorization: Bearer $API_KEY" ``` **Reading lineage fields** When an order rolls into a new auction cycle, Match creates a new order linked to the original. The `lineage` object lets you trace the full chain: * `lineage.parentOrderId`: the UUID of the order this one rolled from. `null` if this is the original order. * `lineage.childOrderId`: the UUID of the order this one rolled into. `null` if the order hasn't rolled yet, or if it was cancelled. To reconstruct the full history of a rolled order, start with any order in the chain and follow `parentOrderId` backward or `childOrderId` forward until you reach `null`. **Reading the fill object** The `fill` field is `null` until the order is matched. Once matched, it contains: ```json theme={null} { "fill": { "filledAmount": { "amount": "500.00", "currency": "USD" }, "unfilledAmount": { "amount": "0.00", "currency": "USD" }, "clearingFeeBps": "3", "matchedAt": "2026-08-17T00:05:00Z" } } ``` A non-zero `unfilledAmount` indicates a partial fill. In that case, check `lineage.childOrderId` to find the follow-on order that was created for the unfilled portion according to your `postFillAction` election. ## Order status lifecycle | Status | Description | | - | - | | `pending` | Accepted and queued for the current auction. Not yet matched or settled. | | `settling` | Matched in the auction. Funds are moving between counterparties. | | `filled` | The entire order matched and settlement is complete. | | `partial_fill` | Only part of the order matched. The unfilled portion followed your `postFillAction` election. | | `unfilled` | The auction closed with no fill for this order. The order followed your `postFillAction` election. | | `cancelled` | You canceled the order before it matched. | | `failed` | The order matched but the underlying funding never settled. No trade occurred. | ## Error reference | Code | HTTP | Meaning | | - | - | - | | 137002 | 400 | One or more wallet IDs in the request are invalid. | | 137003 | 400 | One or more wallet IDs were not found. | | 137004 | 409 | Idempotency key reused with different parameters. | | 137006 | 409 | Self-match violation: you already have an open order on the opposite side of this auction. | | 137007 | 400 | The fiat account cannot be used for this burn order. | | 137008 | 400 | Maximum orders per auction reached. Wait for the next auction cycle. | | 137009 | 400 | Exceeds your transaction limit. | | 137010 | 400 | This account is not eligible to place orders. | # How-to: Subscribe to real-time updates Source: https://developers.circle.com/circle-match/howtos/subscribe-to-real-time-updates Open a WebSocket connection to Match and subscribe to market or account channels for live auction and order events. The Match WebSocket API delivers real-time auction and account events without polling. You subscribe to the `market` channel for public auction state, the `account` channel for private order and fill events, or both. Authentication uses a short-lived, single-use JWT ticket you create immediately before opening the socket. ## Prerequisites Before you begin, ensure that you've: * Obtained a Circle API key with Match access * Completed onboarding as a burn-side or mint-side participant (or both) ## Steps ### Step 1. Create a connection ticket Call `POST /v1/match/ws/ticket` to get a single-use JWT. The ticket is short-lived, so create it immediately before you open the socket. ```bash theme={null} curl -X POST https://api-sandbox.circle.com/v1/match/ws/ticket \ -H "Authorization: Bearer $API_KEY" ``` A successful response contains the ticket string: ```json theme={null} { "data": { "ticket": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." } } ``` <Note> Each ticket is single-use and authenticates exactly one WebSocket connection. Do not reuse a ticket after it has been used to open a connection. </Note> ### Step 2. Open the connection Pass the following two `Sec-WebSocket-Protocol` values in the upgrade request: * `circle-match.v1`: identifies the protocol version * `ticket.<jwt>`: your ticket value, prefixed with `ticket.` The server validates the ticket before completing the upgrade. If the ticket is missing, expired, or already used, the server rejects the connection with HTTP 401. ```bash theme={null} wscat -c "wss://api-sandbox.circle.com/v1/match/ws" \ --subprotocol "circle-match.v1" \ --subprotocol "ticket.$TICKET" ``` Replace `$TICKET` with the `ticket` value from the previous step. ### Step 3. Handle the hello frame and subscribe The server sends a `hello` frame immediately after the connection is established: ```json theme={null} { "type": "hello", "entityId": "550e8400-e29b-41d4-a716-446655440000", "serverTime": "2026-09-21T14:00:00.000Z" } ``` After receiving `hello`, send a `subscribe` message for each channel you want to receive events from. To subscribe to both channels, send two messages: ```json theme={null} { "type": "subscribe", "channel": "market" } ``` ```json theme={null} { "type": "subscribe", "channel": "account" } ``` The server acknowledges each subscription with a `subscribed` frame: ```json theme={null} { "type": "subscribed", "channel": "market" } ``` The server also sends periodic `keepalive` frames with a `serverTime` field to confirm the connection is healthy. If a subscription request is invalid or authorization fails, the server sends an `error` frame with a `channel` and `error` field. ### Receive events #### Session frames | Frame type | When sent | Key fields | | - | - | - | | `hello` | Immediately on connect | `entityId`, `serverTime` | | `keepalive` | Periodically | `serverTime` | | `subscribed` | After subscription acknowledged | `channel` | | `error` | On invalid subscription or auth error | `channel`, `error` | #### Market channel events (public) Any valid ticket holder can subscribe to the `market` channel. On subscribe, the server delivers a `snapshot` of the current auction state, then streams incremental events as the auction progresses. | Event | When | Key fields | | - | - | - | | `snapshot` | On subscribe | Full current auction state | | `auction_opened` | When a new auction opens | `auctionId`, `lockAt`, `clearAt` | | `auction_locked` | When the lock window opens | `auctionId` | | `auction_cleared` | When the auction clears | `auctionId`, `clearingFeeBps`, `matchedSizeCents` | | `indicative_updated` | Periodically during open phase | `indicativeFeeBps`, `netImbalanceCents` | Key fields present on market events: * `phase`: current auction phase (`open`, `locked`, `settling`) * `indicativeFeeBps`: the fee that would clear if the auction settled now * `matchableSizeCents`: volume that would match at the indicative fee * `netImbalanceCents`: difference between burn-side and mint-side volume #### Account channel events (private) The `account` channel delivers per-entity events for your own orders and fills. On subscribe, the server delivers an `account_snapshot` with your current open orders and balance. | Event | When | Key fields | | - | - | - | | `account_snapshot` | On subscribe | Current open orders and balance | | `order_received` | When a new order is accepted | `orderId`, `status` | | `order_modified` | When an order fee is modified | `orderId`, `feeBps` | | `order_canceled` | When a single order is canceled | `orderId` | | `order_canceled_all` | When cancel-all is called | `orderIds` | | `account_cleared` | When the auction clears | `fills`, `forwardOrders`, `feesRebatedCents` | Key fields on `account_cleared`: * `fills`: array of per-order fill breakdowns, each with `filledAmount`, `unfilledAmount`, `clearingFeeBps`, and `matchedAt` * `forwardOrders`: array of orders rolled into the next auction * `feesRebatedCents`: signed integer; positive means a mint-side rebate, negative means a burn-side fee paid ### Step 4. Handle reconnection If the connection drops, follow these steps to restore your subscription: 1. Create a new ticket using `POST /v1/match/ws/ticket`. The previous ticket is consumed or expired and cannot be reused. 2. Open a new socket using the new ticket as described in the preceding "Open the connection" and "Handle the hello frame and subscribe" sections. 3. Re-send `subscribe` messages for all channels you want to receive. 4. The server delivers a fresh `snapshot` (market) or `account_snapshot` (account) for each channel. <Note> The server does not replay events missed during a disconnection. If your connection dropped while an auction was clearing and you missed the `account_cleared` event, call `GET /v1/match/orders` to reconcile any fills that occurred while you were offline. </Note> # How-to: Withdraw funds Source: https://developers.circle.com/circle-match/howtos/withdraw-funds Convert your Match-only USDC back to USD through a no-fee wire to your linked fiat account. The withdrawal endpoint is for mint-side participants only. It converts your Match-only USDC balance to USD and delivers the funds by wire to your linked fiat account. Unlike a standard Circle Mint burn, no burn fee applies to this transaction. Burn-side participants do not use this endpoint. Their USDC releases automatically when orders fill or are cancelled. ## Prerequisites Before you begin, ensure that you've: * Obtained a Circle API key with Match access * Completed mint-side onboarding and wired funds to your Match fiat account (see [Fund your account](/circle-match/howtos/fund-your-account)) * Confirmed that your `usdc.available` balance covers the withdrawal amount by calling `GET /v1/match/account` ## Steps ### Step 1. Submit a withdrawal Call `POST /v1/match/withdrawals` with the amount you want to withdraw. The amount must not exceed your `usdc.available` balance. The `usdc.available` field reflects only the portion of your balance that is free to use. Any balance reserved by open resting orders appears in `usdc.reserved` and is not available for withdrawal. If your reserved balance is too high, cancel your resting orders first to free that balance before submitting the withdrawal. See [Cancel and modify orders](/circle-match/howtos/cancel-and-modify-orders) for details. ```bash theme={null} curl -X POST https://api-sandbox.circle.com/v1/match/withdrawals \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "idempotencyKey": "550e8400-e29b-41d4-a716-446655440000", "amount": { "amount": "1000.00", "currency": "USD" }, "fiatAccountId": "550e8400-e29b-41d4-a716-446655440001" }' ``` A successful request returns `201 Created`: ```json theme={null} { "data": { "id": "80dc9037-b0b7-42fb-a140-de5ebbde2cf8", "status": "pending" } } ``` The withdrawal status starts as `pending`. Circle burns the Match-only USDC and wires the equivalent USD to your linked fiat account. No standard Circle Mint burn fee applies. This is a fee-free exit path for Match-only USDC. For background on why this USDC is restricted and how the exit path works, see [Funding model](/circle-match/concepts/funding-model). <Note> Burn-side participants do not use this endpoint. Their USDC is held in a standard Circle Mint wallet and releases automatically when orders fill or are canceled. There is no separate withdrawal step for burn-side balances. </Note> ## Error reference | Code | HTTP | Meaning | | - | - | - | | 137001 | 400 | Insufficient available balance. The requested amount exceeds your `usdc.available`. Check your balance and cancel any resting orders to free reserved funds before retrying. | | 137009 | 400 | Exceeds your transaction limit. | | 138001 | 400 | Withdrawal amount exceeds available balance. Verify your `usdc.available` before retrying. | | 138002 | 400 | The withdrawal request could not be processed. | | 138003 | 404 | No Match wallet found. The entity does not have a Match account. | | 138004 | 400 | The destination account is invalid or cannot be used for this withdrawal. | # Place your first order Source: https://developers.circle.com/circle-match/quickstarts/place-your-first-order Submit a burn order to the Match sandbox and check its status. A burn order redeems USDC for USD through Match's batch auction. Submissions are asynchronous; fill results arrive after the auction cycle closes. ## Prerequisites Before you begin, ensure that you've: * Obtained a Circle API key with Match access * Created a Circle Mint account and funded it with a USDC balance to cover the burn order * Added a linked fiat account in Circle Mint to receive settlement proceeds See [Funding model](/circle-match/concepts/funding-model) for how USDC is reserved on the burn side. ## Step 1: Place the order Send a `POST /v1/match/orders` request to create a burn order. The `idempotencyKey` you supply becomes the `orderId` for all subsequent lookups. Use a unique UUID v4 for each new order. ```bash theme={null} curl -X POST https://api-sandbox.circle.com/v1/match/orders \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "idempotencyKey": "550e8400-e29b-41d4-a716-446655440000", "orderType": "BURN", "amount": { "amount": "500.00", "currency": "USD" }, "feeBps": "5", "postFillAction": "cancel", "sourceWalletId": "$WALLET_ID", "fiatAccountId": "$FIAT_ACCOUNT_ID" }' ``` For the full request schema and field descriptions, see [Place order](/api-reference/circle-match/all/place-order) in the API reference. A successful submission returns `202 Accepted`: ```json theme={null} { "data": { "auctionId": 42, "orderId": "550e8400-e29b-41d4-a716-446655440000", "status": "pending" } } ``` The `orderId` matches the `idempotencyKey` you supplied. The `auctionId` identifies the auction cycle your order entered. ## Step 2: Check order status Fill is asynchronous. The `status` stays `pending` until the auction cycle closes and matching runs. Poll `GET /v1/match/orders/{id}` using your `orderId` to check progress. ```bash theme={null} curl https://api-sandbox.circle.com/v1/match/orders/550e8400-e29b-41d4-a716-446655440000 \ -H "Authorization: Bearer $API_KEY" ``` While the auction is still open, you'll see: ```json theme={null} { "data": { "orderId": "550e8400-e29b-41d4-a716-446655440000", "auctionId": 42, "lineage": { "parentOrderId": null, "childOrderId": null }, "orderType": "BURN", "amount": { "amount": "500.00", "currency": "USD" }, "feeBps": "5", "postFillAction": "cancel", "status": "pending", "createdAt": "2026-08-17T00:00:00Z", "updatedAt": "2026-08-17T00:00:00Z", "sourceWalletId": "1000001234", "fiatAccountId": "550e8400-e29b-41d4-a716-446655440001", "fill": null } } ``` Once the auction clears, `status` transitions to one of the following terminal or settlement values: | Status | Meaning | | - | - | | `settling` | Matched; funds are moving to settlement | | `filled` | The full order amount matched | | `partial_fill` | Only part of the order matched | | `unfilled` | The auction closed with no match | | `cancelled` | The order was cancelled before it matched | | `failed` | USDC funding was not received before the auction closed; no trade occurred | After a match, the response includes a `fill` object with the cleared amounts and fee: ```json theme={null} { "data": { "orderId": "550e8400-e29b-41d4-a716-446655440000", "auctionId": 42, "lineage": { "parentOrderId": null, "childOrderId": null }, "orderType": "BURN", "amount": { "amount": "500.00", "currency": "USD" }, "feeBps": "5", "postFillAction": "cancel", "status": "filled", "createdAt": "2026-08-17T00:00:00Z", "updatedAt": "2026-08-17T00:05:00Z", "sourceWalletId": "1000001234", "fiatAccountId": "550e8400-e29b-41d4-a716-446655440001", "fill": { "filledAmount": { "amount": "500.00", "currency": "USD" }, "unfilledAmount": { "amount": "0.00", "currency": "USD" }, "clearingFeeBps": "3", "matchedAt": "2026-08-17T00:05:00Z" } } } ``` `clearingFeeBps` reflects the actual fee applied at settlement, which will not exceed your `feeBps` limit. <Note> As an alternative to polling, subscribe to the WebSocket account channel to receive real-time order status events without repeated HTTP requests. </Note> # WebSocket reference Source: https://developers.circle.com/circle-match/references/websocket-reference Complete reference for the Match WebSocket protocol, including connection setup, session frames, client messages, channel events, and reconnection behavior. The Match WebSocket API delivers real-time auction state and account updates over a persistent connection. All monetary values in WebSocket events are integer cents, not the REST `Money` object. For example, \$10.00 is represented as `1000`. ## Connection Connect by sending a WebSocket upgrade request to the appropriate endpoint. | Environment | Endpoint | | - | - | | Production | `wss://api.circle.com/v1/match/ws` | | Sandbox | `wss://api-sandbox.circle.com/v1/match/ws` | Include both of the following protocol values in the `Sec-WebSocket-Protocol` header of the upgrade request: * `circle-match.v1` * `ticket.<jwt>`: replace `<jwt>` with the ticket token from `POST /v1/match/ws/ticket` ## Authentication Obtain a WebSocket ticket before opening the connection. **Endpoint:** `POST /v1/match/ws/ticket` No request body is required. The response contains a short-lived, single-use token: ```json theme={null} { "data": { "ticket": "eyJ..." } } ``` Obtain the ticket immediately before opening the socket. The server validates the ticket during the upgrade handshake. An invalid, expired, or missing ticket returns HTTP 401 and the connection is not established. ## Session frames The server sends the following session-level frames to the client. | Frame type | When sent | Fields | | - | - | - | | `hello` | Immediately after a successful upgrade | `type: "hello"`, `entityId` (string), `serverTime` (ISO 8601) | | `keepalive` | Periodically while connected | `type: "keepalive"`, `serverTime` (ISO 8601) | | `subscribed` | After a subscribe message is acknowledged | `type: "subscribed"`, `channel` (`"market"` or `"account"`) | | `error` | On an invalid subscription or authentication error | `type: "error"`, `channel` (string or null), `error` (string) | ## Client messages Send subscribe messages to the server after receiving the `hello` frame. You can subscribe to multiple channels in a single session. | Message type | Fields | Notes | | - | - | - | | `subscribe` | `type: "subscribe"`, `channel` (`"market"` or `"account"`) | Send after `hello`. Multiple subscribe messages are allowed. | ## Market channel The market channel is public and delivers real-time auction state. **Subscribe:** ```json theme={null} { "type": "subscribe", "channel": "market" } ``` ### Market channel events | Event type | When sent | Key fields | | - | - | - | | `snapshot` | On subscribe | All fields listed in the [market channel fields](#market-channel-f
프로젝트로 돌아가기