# Environments and hosts

Polyester's environments, the public host for each interface, where each environment's contracts are published, and the conventions every API shares.

Polyester runs separate environments, each with its own hosts, accounts, API keys, and contracts. Nothing carries over between them: create an API key in the environment you connect to, and point your client at that environment's hosts. Testnet is the public environment today; Mainnet is coming soon.

## Environments

| Environment | Use it for                                            |
| ----------- | ----------------------------------------------------- |
| Testnet     | Building and testing an integration before production |
| Mainnet     | Production trading. Coming soon                       |

Each environment runs its own release, so a contract can change when that environment is upgraded. Build against the contracts published for the environment you target, described [below](#contracts-per-environment), and regenerate your clients when they change.

## Hosts

Each environment has two kinds of host: API hosts for REST, ConnectRPC, and the realtime streams, and one trade host for the low-latency trade WebSockets. The global API host is shown here; Testnet also has [regional API hosts](#regional-api-hosts).

| Host              | Testnet                           |
| ----------------- | --------------------------------- |
| API host (global) | `api.testnet.polyester.com`       |
| Trade host        | `trade.api.testnet.polyester.com` |

Every interface uses TLS: `https://` for HTTP requests and `wss://` for WebSockets.

| Interface                       | Host       | Path                            |
| ------------------------------- | ---------- | ------------------------------- |
| REST                            | API host   | `/v1/...`                       |
| ConnectRPC                      | API host   | `/<package>.<Service>/<Method>` |
| Realtime WebSocket              | API host   | `/connection/websocket`         |
| Private WebSocket (your orders) | API host   | `/v1/ws/private`                |
| SBE trade WebSocket             | Trade host | `/ws/trade.sbe`                 |
| Protobuf trade WebSocket        | Trade host | `/ws/trade.proto`               |

For example, the spot configuration is [`GET https://api.testnet.polyester.com/v1/spot/config`](https://testnet.polyester.com/docs/api-docs/rest/GET/v1/spot/config) on REST and [`POST https://api.testnet.polyester.com/marketdata.v1.MarketDataService/GetSpotConfig`](https://testnet.polyester.com/docs/api-docs/connect/marketdata.v1.MarketDataService/GetSpotConfig) on ConnectRPC. Open the realtime WebSocket at `/connection/websocket`; Cloudflare can refuse an upgrade at the host root. Tokens for the realtime and private WebSockets come from `GET /v1/rt/token` and `GET /v1/rt/subscribe` on the API host; see [WebSocket session model](https://testnet.polyester.com/docs/developer-docs/shared-concepts/websocket-session-model).

On Testnet, API clients may be refused with HTTP 403 when they open the private WebSocket while access is being enabled. See [Private WebSocket](https://testnet.polyester.com/docs/developer-docs/connectrpc/private-websocket).

### Regional API hosts

Besides the global API host, Testnet has regional API hosts that serve the same REST, ConnectRPC, and realtime routes. Use one when you want a fixed region instead of the global entry point.

| Region  | Testnet host                            |
| ------- | --------------------------------------- |
| Tokyo   | `https://tyo.api.testnet.polyester.com` |
| EU West | `https://bru.api.testnet.polyester.com` |
| US East | `https://iad.api.testnet.polyester.com` |
| US West | `https://pdx.api.testnet.polyester.com` |

The trade WebSockets have no regional hosts. Always connect them to the environment's trade host. To choose between the global and a regional host, and to keep connections reliable, see [Regions and connectivity](https://testnet.polyester.com/docs/developer-docs/getting-started/regions-and-connectivity).

> **Mainnet hosts**
>
> Mainnet is not live yet, so it has no public API or trade hosts. Its hosts will be listed here at launch.

## Contracts per environment

The public contracts for each environment are published in the [polyester-proto](https://github.com/Fabric-Labs/polyester-proto) repository, one branch per environment. Use the `testnet` branch for Testnet; Mainnet gets its own branch at launch.

Each branch has a `manifest.json` at its root. Its `paths` object names where everything is, and `publicDescriptorSha256` fingerprints the compiled descriptor, so a changed value tells you the contracts changed:

| Path         | Contents                                                                             |
| ------------ | ------------------------------------------------------------------------------------ |
| `proto`      | The public `.proto` files, for ConnectRPC and the Protobuf WebSockets                |
| `descriptor` | A compiled descriptor set of those files                                             |
| `openapi`    | The OpenAPI documents for REST                                                       |
| `sbe`        | The SBE schema for the SBE trade WebSocket. Its file name carries the schema version |
| `docs`       | Generated API reference data, including the error catalog                            |

The SDKs are generated from the same contracts. The [API reference](https://testnet.polyester.com/docs/api-docs) is built from them too. How changes are announced, and how to update safely, is in [API changes and versioning](https://testnet.polyester.com/docs/developer-docs/getting-started/api-changes-and-versioning).

## Shared conventions

These conventions hold across the REST and ConnectRPC APIs unless an endpoint's reference says otherwise.

### Timestamps

A timestamp's field name tells you its form and unit:

| Field form                                        | Value                                                                                |
| ------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `createdAt`, `executedAt`, and other `*At` fields | RFC 3339 date-time strings in UTC on REST, `google.protobuf.Timestamp` on ConnectRPC |
| `tsNs`, `acceptedTsNs`, and other `*Ns` fields    | Nanoseconds since the Unix epoch, as a decimal string in JSON                        |
| `*Sec` fields                                     | Seconds, either since the Unix epoch or as a duration, as the field describes        |
| `*Ms` fields                                      | Milliseconds, usually a duration such as `retryAfterMs`                              |

Time-range filters on REST, such as `startTime` and `endTime` on order history, trades, and candles, take RFC 3339 timestamps. Transfer history is the exception: its `timestampMin` and `timestampMax` filters take microseconds since the Unix epoch, as the [`GET /v1/transfers` reference](https://testnet.polyester.com/docs/api-docs/rest/GET/v1/transfers) describes.

### Large integers

ConnectRPC's JSON encoding carries every 64-bit integer as a string, and REST does for most fields, such as IDs, `bookSeq`, and `*Ns` timestamps. A few REST and WebSocket JSON fields are plain numbers instead: the REST order book's `ts` (Unix milliseconds), the order book WebSocket deltas' `bookSeqStart`, `bookSeqEnd`, and `ts`, and request integers such as `newQtyScaled` and `maxSlippageTicks`. The API reference gives each field's type. Parse 64-bit values as 64-bit integers or exact decimals, never as floating-point numbers.

### Pagination

List endpoints page with an opaque cursor. Pass the cursor from the previous response back unchanged, and stop when it comes back empty. Both REST and ConnectRPC JSON name it `pageToken` in the request and `nextPageToken` in the response; the `.proto` fields are `page_token` and `next_page_token`. A page can hold fewer rows than the limit, or none, before the end. Time-range and trade-ID cursors are covered in [REST getting started](https://testnet.polyester.com/docs/developer-docs/rest/getting-started#pagination-patterns).

### Identifiers

Orders, accounts, Subaccounts, and other resources have public IDs. REST writes them as short base58 strings; ConnectRPC carries them as `fixed64` numbers. Both forms name the same resource. See [Public IDs](https://testnet.polyester.com/docs/developer-docs/shared-concepts/public-ids).

### Prices, quantities, and amounts

REST carries prices, quantities, and amounts as decimal strings, such as `"64250.5"`. ConnectRPC carries them as scaled integers: price ticks, quantities at the Asset's scale, and 18-decimal `*_e18` amounts. Read each field's scale before converting. See [Scaled integers](https://testnet.polyester.com/docs/developer-docs/connectrpc/scaled-integers).

### Errors

Every interface reports a stable error code. See [Error responses](https://testnet.polyester.com/docs/developer-docs/error-handling/error-responses) and [Error codes](https://testnet.polyester.com/docs/developer-docs/error-handling/error-codes).
