> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ekiden.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# Market Maker Integration Guide

This document explains how market makers can authenticate and integrate with the Ekiden Gateway HTTP API and WebSocket feeds exposed by the Axum service. It mirrors what is generated by utoipa and available in Swagger UI.

> Swagger UI

> OpenAPI JSON

***

## **1.  Service Overview**

* **Protocol:** HTTP/1.1 + WebSocket
* **Default Port:** 3010
* **Base REST Path:** /api/v1
* **CORS:** Open (all origins/headers/methods allowed)
* **Auth:** JWT Bearer
* **Modules exposed:** orders, fills, user, deposits, withdraws (all are nested under /api/v1)
* **WebSocket:** GET /ws (top‑level; not under /api/v1)

> The service depends on external gRPC backends:

* SEQUENCER\_GRPC\_URL → Sequencer
* REFEREE\_GRPC\_URL → Referee

***

## **2.  Authentication Flow**

Authentication is performed via the `/api/v1/authorize` endpoint. Clients provide their `partyId`, and on successful authorization, the API returns a JWT bearer token that can be used to access authenticated endpoints.

### **Endpoint**

```text theme={null}
POST /api/v1/authorize
```

**Summary:** Authorize a user using their Canton Party ID and issue a JWT bearer token.

**Tags:** Auth

**Sec:** no auth required for this call.

### **Request Body –**

### **AuthorizeParams**

```json theme={null}
{
  "public_key": "<Canton Party ID>",
  "signature": "",
  "timestamp_ms": 1731541800000,
  "nonce": "random-unique-string"
}
```

* public\_key: Canton Party ID associated with the user.
* timestamp\_ms: Unix time in milliseconds.
* nonce: Unique value generated for the authorization request.

> The server uses the provided Canton Party ID to identify and authorize the user. On successful authorization, the API returns a JWT bearer token and the associated user ID.

### **Responses**

* **200 OK** – AuthorizeResponse

```text theme={null}
{
  "token": "<jwt>",
  "user_id": "<user_id>"
}
```

* **400 Bad Request** – invalid signature or public key
* **500 Internal Server Error**

### **Example – cURL**

```bash theme={null}
curl -X POST "http://<host>:3010/api/v1/authorize" \
  -H "Content-Type: application/json" \
  -d '{
    "public_key": "<CANTON_PARTY_ID>",
    "signature": "",
    "timestamp_ms": <NOW_MS>,
    "nonce": "<UNIQUE_NONCE>"
  }'
```

On success, save the returned token and include it in the Authorization header:

```text theme={null}
Authorization: Bearer <token>
```

***

## **3.  Using the JWT**

All authenticated REST endpoints require the standard HTTP **Bearer** token.

```text theme={null}
Authorization: Bearer <token>
```

The OpenAPI spec declares a bearer\_auth security scheme, and all protected routes are annotated to use it.

***

## **4.  REST API Surface**

All REST API endpoints are available under the `/api/v1` base path.

The API includes the following main endpoint groups:

* `/api/v1/market/*` – Public market data, including tickers, order book, klines, recent trades, funding history, and risk data
* `/api/v1/order/*` – Order placement, amendment, cancellation, and order history
* `/api/v1/execution/*` – Trade execution history
* `/api/v1/position/*` – Position data, leverage configuration, closed PnL, and trading stops
* `/api/v1/account/*` – Account balances, funding, and account statistics
* `/api/v1/user/*` – User account data, subaccounts, API keys, referrals, rewards, and related user-specific resources

Refer to the OpenAPI specification for the complete list of available endpoints, request parameters, and response schemas.

> Authoritative contract:

### **Example – Authenticated request**

```bash theme={null}
curl -X GET "http://<host>:3010//api/v1/position/list" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "sub_account_address=<SUB_ACCOUNT_ADDRESS>"
```

> Tip: A `401 Unauthorized` response may indicate missing, invalid, or expired authentication credentials. Obtain a new token via `/api/v1/authorize` if needed.

***

## **5.  WebSocket Streaming**

* **Endpoint:** GET ws\://\<host>:3010/ws
* **Purpose:** Real-time event feed (emitted via an internal broadcast channel)
* **Auth:** Implementation-specific. If private streams are offered, you may be required to present the JWT (e.g., as the first message or via subprotocol). Consult the deployed config/team for the expected pattern.

### **Example – JavaScript**

```text theme={null}
const ws = new WebSocket("ws://<host>:3010/ws");
ws.onopen = () => {
  // If auth is required, send your token here (example only):
  // ws.send(JSON.stringify({ op: "auth", token: YOUR_JWT }));
};
ws.onmessage = (e) => console.log("event", e.data);
ws.onclose = () => console.log("closed");
```

> Event payloads are defined by the server’s ws::EventWithChannel. Use your environment’s Swagger or internal docs for the exact schema of each channel.

***

## **6.  Local Testing**

1. Export backend endpoints:

```text theme={null}
export SEQUENCER_GRPC_URL=grpc://<sequencer-host>:<port>
export REFEREE_GRPC_URL=grpc://<referee-host>:<port>
```

1. Run the API (binds 0.0.0.0:3010):

```text theme={null}
cargo run -p <your-api-crate>
```

1. Open Swagger UI:

```text theme={null}
<http://localhost:3010/swagger-ui>
```

***

## **7.  Error Handling**

* **400** – Invalid signature or public key on /authorize.
* **401** – Missing/expired/invalid Authorization: Bearer token on protected routes.
* **5xx** – Internal server errors or dependency failures (database, gRPC backends).

Errors are logged with tracing and the service emits structured JSON logs in non‑debug builds.

***

## **8. Security Notes**

* Use HTTPS in production (behind a reverse proxy / LB) and store tokens securely.
* JWT validity/claims are generated by AuthClaims::generate\_with\_token.
* Rate limits are not enforced by this service; deploy behind an API gateway if needed.

***

## **9. FAQ**

**Q: What encodings are expected for public\_key, signature, and nonce?**

A: The server treats them as strings and passes to the Ed25519 verifier. Use the same encoding your SDK produces (commonly base64 or hex). Confirm with your Ekiden contact if unsure. Nonce must be Base64URL (A‑Z, a‑z, 0‑9, -, \_), 8–64 chars.

**Q: Is /ws namespaced under /api/v1?**

A: No. It is mounted at the root /ws.

**Q: Where can I find the exact schemas for Orders/Fills/etc.?**

A: Open Swagger UI at /swagger-ui or fetch /api-docs/openapi.json. Those are generated from the code and are the source of truth.

***

## **10. Changelog**

* **v1.1** – Added `id` field to WebSocket aggregated trades (`trade/{market_addr}`) events. Deterministic per aggregated price/side in an execution: hash(market\_addr, price, side, seq, timestamp). Use (`market_addr`, `id`) as a stable key for upserts / dedupe.
* **v1.0** – Initial draft based on Axum service wiring and utoipa annotations provided in source.
