Skip to main content
POST
Create API key
The response body shown here is a static example, not live data. After you click Send, your live result appears in a separate panel headed 200 OK. The panel under the status-code tabs is a fixed sample from the spec — its field values (fees, prices, sizes, IDs, timestamps) are placeholders. Use Send, or call the endpoint, for current values.
Create an API key for the ethereum address. No address or account parameter is required; all keys are associated with the master account.

Signing the request

The request is authenticated by a secp256k1 EIP-712 typed-data signature (eth_signTypedData_v4) produced by the wallet that owns address, so wallets render each field and institutional / MPC signers can whitelist on the domain. Sign the typed data below, then split the 65-byte result into {r, s, v} for the signature field. The gateway recovers the signer and rejects the request with HTTP 401 if the recovered address does not equal address. Domain API keys are pure off-chain authentication, so the domain has no verifyingContract (the field is optional per EIP-712):
Types
Message
apiWalletPublicKey is the request’s publicKey field (64 hex chars, no 0x); validUntil is epoch ms, the same value as the request field. Always send validUntil explicitly and sign that value — if the body omits it, the server verifies against its own default (now + 14 days), which will not match what you signed. Per-environment domain parameters Complete eth_signTypedData_v4 call (ethers v6 / viem)

Legacy EIP-191 signatures (deprecated)

This endpoint previously accepted an EIP-191 personal_sign signature over the canonical JSON message
(keys in this exact order, no whitespace, no trailing newline). During the migration window the server accepts either scheme: it verifies the EIP-712 signature first and falls back to legacy EIP-191. EIP-191 is deprecated and will be rejected once the migration window closes — migrate existing integrations to EIP-712 typed data; new integrations must use EIP-712 only.

Public-key ownership

A public key is a globally unique credential: auth resolves the owning account from api_keys_by_key. createApiKey rejects registering a public key already owned by a different account with HTTP 409 — including keys that have expired but were never revoked. Re-registering a key the caller already owns (renew / rewrite validUntil) is allowed.

Body

application/json
address
string
required

Ethereum address to associate with the account.

Pattern: ^(0x|0X)?[0-9a-fA-F]{40}$
Example:

"0x742d35cc6634c0532925a3b844bc9e7595f2bd18"

publicKey
string
required

Hex-encoded Ed25519 public key. Becomes the API key.

Required string length: 64
Pattern: ^[0-9a-fA-F]{64}$
Example:

"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"

apiWalletName
string
required

Name of the API wallet (included in the signing message).

Required string length: 1 - 64
Example:

"Arcus"

signature
object
required

secp256k1 EIP-712 typed-data signature (r, s, v) over the CreateApiKey payload (eth_signTypedData_v4), produced by the wallet that owns address. See the POST /v1/createApiKey endpoint description for the exact domain, types, and message. During the migration window the deprecated legacy EIP-191 personal_sign scheme is also accepted. Requests where the recovered signer does not equal address are rejected with HTTP 401.

validUntil
integer<int64>

Expiration timestamp (epoch ms). Must be between 1 day and 180 days from the server's current time (inclusive). If omitted, defaults to 14 days from now. Explicit values outside the [now+1d, now+180d] window are rejected with HTTP 400.

Required range: x >= 1

Response

API key creation accepted. The request has been accepted but the key is not yet usable for authenticated requests; the caller must wait briefly for it to be ingested before the returned api_key resolves.

apiKey
string
required

Newly generated API key (hex string).

address
string
required

20-byte EVM address as hex: optional 0x or 0X prefix and exactly 40 hexadecimal digits. API responses normalize to lowercase af after 0x.

Pattern: ^(0x|0X)?[0-9a-fA-F]{40}$
createdAt
integer<int64>
required

Creation timestamp (epoch microseconds).

accountIndex
integer

Account index for this API key (optional; omit when not applicable).

Required range: 0 <= x <= 9
validUntil
integer<int64>

Expiration timestamp (epoch ms). Echoes the client-supplied expiry, so it stays in milliseconds. Absent if no expiry.