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

# Security

> How we protect your keys, your data and your capital.

This page walks through each layer between a request and your capital, and what it protects against. Most of these are properties of how the system is built rather than settings someone has to get right. At the front door, where a request or a WebSocket handshake is authenticated, a check that cannot decide rejects the request.

For the signing details see [Authentication](/authentication).

For what we can and cannot do with your money, see [Custody and key management](/custody-and-key-management).

## Request signing

Every API request is signed with an Ed25519 key that you generate. You register the public key with us and keep the private key. We never see it, so a full copy of our database gives an attacker nothing to forge a request with.

The signature covers the method, the path, the query string, a timestamp and a hash of the body. Change any of them and the signature no longer verifies. A signed read cannot be turned into a write, and a signed order cannot have its size edited in transit.

We verify the signature before we parse the body. A request that fails verification is rejected without its contents being read.

Timestamps have to be within 30 seconds of our clock, so a captured request stops being useful quickly. If your clock is off, the `time` endpoint returns ours and is the one call that does not need a timestamp.

The WebSocket handshake is signed the same way, with `WS` in place of the HTTP method. A handshake signature cannot be reused against a REST route, and vice versa.

## Scope comes from the key

Each API key is created for one trader in one pod, and that pairing cannot be changed later.

The request itself never names a pod or an organization. `/orders` means your orders in your pod, because the key already says which pod that is. There is no way to write a request for someone else's pod, so there is no permission check that could be misconfigured to allow one.

A key also carries a capability. A `trade` key can call venue endpoints; a `data` key can only use discovery and the stream.

See [Traders and permissions](/traders-and-permissions).

## Revocation

You can revoke at three levels, and each one is independent of the others:

> **Revoke the key**
>
> One credential stops working. The trader's other keys are unaffected.

> **Remove the trader**
>
> Every key the trader holds stops working, in every pod, and so does their sign-in.

> **Remove from a pod**
>
> The trader loses access to one pod and keeps the others.

Timing: REST requests stop being accepted within 15 seconds, which is how long we cache a key's status. A live WebSocket is closed at the next periodic check of its key, which runs every 30 seconds. If that check cannot reach the key store, the connection is left open and checked again on the next pass rather than cut. If a key is compromised, revoke it first, then contact us.

Every one of these failures, along with a bad signature or an unknown key, returns the same `401 UNAUTHORIZED`. If the responses were different, someone without a valid key could work out which key IDs exist by watching the error codes. We record the actual reason on our side, so support can tell you what happened.

## Data isolation

Isolation between pods is enforced in the database, not left to application code.

Every table that holds orders, fills, positions, balances, wallets or withdrawal addresses has a row-level security policy. Each tenant-bound operation runs inside a transaction that is bound to one organization and one pod, and the database only returns or accepts rows that match. If no tenant is bound, a read returns nothing and a write is refused. The policy applies to the table owner as well.

So on those operations, even if a query in our code forgot a filter, the database would still not return another pod's rows.

## Venue credentials

When you connect a venue account such as Kalshi, the private key you supply is imported into a hardware security module as a non-extractable key. It cannot be exported afterwards, by us or anyone else. Our database stores a reference to that key and public metadata, and nothing that could be used to sign.

Replacing a credential is done carefully. The new key is imported, test-signed, and checked against the venue with a real authentication before it takes over from the old one. If any step fails, the working credential is untouched.

Removing a credential schedules the key for destruction.

See [Off-boarding and revocation](/off-boarding-and-revocation).

These credentials only let us place and cancel orders. Your cash stays at the venue, in your account.

## Pod wallets

Each pod has its own wallet for on-chain venues. It is created with the pod and cannot be moved to another pod, and no pod can spend from another pod's wallet.

Signing is handled by a custody provider. Our services hold a wallet reference and an address, never the key, so there is no private key in our databases, logs or servers to leak.

## Network

* All traffic to the API is over TLS.
* The database is in a private subnet with no route to the internet, and is encrypted at rest.
* Calls between our own services are signed and verified too. A service does not trust a request just because it came from inside the network.

## Retries and duplicate orders

Order submissions require an idempotency key. If you send the same key with the same order again, you get the original response back. If you send the same key with a different order, you get a conflict error instead of a second order.

This is what makes it safe to retry after a timeout, when you do not know whether the first attempt was received.

Request rates are limited per organization.

See [Rate limits](/rate-limits).

## What you should do

* Keep the private key in a secrets manager. Never commit it or ship it in a config file. Anyone who has it can trade the pod it belongs to.
* One key per trader per pod. Do not share keys between people or services, or you lose the ability to revoke one without affecting the others.
* Rotate keys on a schedule, and immediately if you think one has leaked. Rotation does not affect open positions.
* Keep your system clock in sync. Clock drift shows up as authentication failures that come and go.
* Send an `Idempotency-Key` on every order.
* If a venue credential is compromised, revoke it at the venue as well as here.

> [!NOTE]
>
> To report a security issue, or if you believe a key has been compromised, email [contact@parlayx.com](mailto:contact@parlayx.com).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.