Files
agent-skills/authentication.md
Suhail Kakar 91ee44ae11 add skills
2026-02-19 21:29:35 +05:30

207 lines
6.0 KiB
Markdown

# Authentication
Polymarket uses two-level auth: **L1** (EIP-712 private key signing) to create credentials, **L2** (HMAC-SHA256 API key signing) to authenticate requests. Builder program adds a separate set of **builder headers** for order attribution and relayer access.
## L1 Authentication (Private Key)
L1 proves wallet ownership via EIP-712 signature. Used to create or derive API credentials.
### EIP-712 Domain
```typescript
const domain = {
name: "ClobAuthDomain",
version: "1",
chainId: 137,
};
const types = {
ClobAuth: [
{ name: "address", type: "address" },
{ name: "timestamp", type: "string" },
{ name: "nonce", type: "uint256" },
{ name: "message", type: "string" },
],
};
const value = {
address: signingAddress, // The signing address
timestamp: ts, // The CLOB API server timestamp
nonce: nonce, // The nonce used
message: "This message attests that I control the given wallet",
};
```
### L1 Headers
| Header | Description |
|--------|-------------|
| `POLY_ADDRESS` | Polygon signer address |
| `POLY_SIGNATURE` | CLOB EIP-712 signature |
| `POLY_TIMESTAMP` | Current UNIX timestamp |
| `POLY_NONCE` | Nonce (default: 0) |
### Create / Derive Credentials
```typescript
// TypeScript
const client = new ClobClient("https://clob.polymarket.com", 137, signer);
const creds = await client.createOrDeriveApiKey();
// { apiKey: "uuid", secret: "base64...", passphrase: "string" }
```
```python
# Python
client = ClobClient("https://clob.polymarket.com", key=pk, chain_id=137)
creds = client.create_or_derive_api_creds()
```
**REST endpoints:**
- `POST {host}/auth/api-key` — create new credentials (requires L1 headers)
- `GET {host}/auth/derive-api-key` — derive existing credentials (requires L1 headers)
## L2 Authentication (API Key)
L2 uses HMAC-SHA256 signatures from the API credentials. Required for all `/v1/trade/*` endpoints.
### L2 Headers (all 5 required)
| Header | Description |
|--------|-------------|
| `POLY_ADDRESS` | Polygon signer address |
| `POLY_SIGNATURE` | HMAC signature for request |
| `POLY_TIMESTAMP` | Current UNIX timestamp |
| `POLY_API_KEY` | User's API `apiKey` value |
| `POLY_PASSPHRASE` | User's API `passphrase` value |
### Initialize Trading Client
```typescript
// TypeScript
const client = new ClobClient(
"https://clob.polymarket.com",
137,
signer,
apiCreds, // { apiKey, secret, passphrase }
2, // signatureType
funderAddress // proxy wallet address
);
```
```python
# Python
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=pk,
creds=api_creds,
signature_type=2,
funder=funder_address,
)
```
## Signature Types
| Type | Value | When to Use |
|------|-------|-------------|
| EOA | `0` | Standard Ethereum wallet (MetaMask). Funder is the EOA address and will need POL to pay gas on transactions. |
| POLY_PROXY | `1` | A custom proxy wallet only used with users who logged in via Magic Link email/Google. Using this requires the user to have exported their PK from Polymarket.com and imported into your app. |
| GNOSIS_SAFE | `2` | Gnosis Safe multisig proxy wallet (most common). Use this for any new or returning user who does not fit the other 2 types. |
The **funder** is the address holding funds. For proxy wallets, find it at polymarket.com/settings. Proxy wallets are auto-deployed on first Polymarket.com login.
## Builder Headers
Builder authentication is separate from L1/L2. Used for order attribution and relayer access.
### Builder Headers (4 required)
| Header | Description |
|--------|-------------|
| `POLY_BUILDER_API_KEY` | Builder API key |
| `POLY_BUILDER_TIMESTAMP` | Unix timestamp |
| `POLY_BUILDER_PASSPHRASE` | Builder passphrase |
| `POLY_BUILDER_SIGNATURE` | HMAC-SHA256 of request |
### Initialize Client with Builder Config
```typescript
// TypeScript — local signing
import { BuilderConfig, BuilderApiKeyCreds } from "@polymarket/builder-signing-sdk";
const builderCreds: BuilderApiKeyCreds = {
key: process.env.POLY_BUILDER_API_KEY!,
secret: process.env.POLY_BUILDER_SECRET!,
passphrase: process.env.POLY_BUILDER_PASSPHRASE!,
};
const builderConfig = new BuilderConfig({ localBuilderCreds: builderCreds });
const client = new ClobClient(
"https://clob.polymarket.com",
137,
signer,
apiCreds,
2,
funderAddress,
undefined,
false,
builderConfig
);
// Orders automatically include builder headers
```
```python
# Python — local signing
from py_builder_signing_sdk import BuilderConfig, BuilderApiKeyCreds
builder_config = BuilderConfig(
local_builder_creds=BuilderApiKeyCreds(
key=os.environ["POLY_BUILDER_API_KEY"],
secret=os.environ["POLY_BUILDER_SECRET"],
passphrase=os.environ["POLY_BUILDER_PASSPHRASE"],
)
)
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=pk,
creds=api_creds,
signature_type=2,
funder=funder_address,
builder_config=builder_config,
)
```
### Remote Signing
Keep builder credentials on a separate server. Client points to your signing endpoint:
```typescript
// TypeScript client
const builderConfig = new BuilderConfig({
remoteBuilderConfig: { url: "https://your-server.com/sign" },
});
```
```python
# Python client
from py_builder_signing_sdk import BuilderConfig, RemoteBuilderConfig
builder_config = BuilderConfig(
remote_builder_config=RemoteBuilderConfig(url="https://your-server.com/sign")
)
```
Your server receives `{ method, path, body }` and returns the 4 `POLY_BUILDER_*` headers.
## Credential Lifecycle
- **Create**: `client.createApiKey()` — generates new credentials with a nonce
- **Derive**: `client.deriveApiKey(nonce)` — recovers existing credentials if you know the nonce
- **Create or Derive**: `client.createOrDeriveApiKey()` — creates if first time, derives if existing
- **Revoke builder key**: `client.revokeBuilderApiKey()` — invalidate compromised builder credentials
Lost credentials + lost nonce = create fresh credentials. Save your nonce.