> For the complete documentation index, see [llms.txt](https://hinkal-team.gitbook.io/hinkal/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hinkal-team.gitbook.io/hinkal/hinkal-api/api-reference/create-session.md).

# Create Session

## Open an authentication session

> Registers a session for the caller's wallet using secp256k1 request signing.\
> \
> \*\*Setup (all chains):\*\*\
> 1\. Generate a secp256k1 key pair on the client (32 random bytes → private key; derive compressed 33-byte public key).\
> 2\. Send \`clientPublicKey\` (compressed secp256k1, 33 bytes = 66 hex chars) in the request body.\
> 3\. Sign the raw request body with the secp256k1 private key (SHA-256 hash then compact ECDSA\
> &#x20;  signature) — no route binding. This is the only route not bound to a \`"\<METHOD> \<routePath>"\`\
> &#x20;  prefix, since no session exists yet to bind against.\
> 4\. Include \`x-hinkal-request-signature: \<hex\_compact\_signature>\` in request headers.\
> 5\. Use the same key pair to authenticate all subsequent requests for this session — every\
> &#x20;  other route binds the signature to its own route path (see \`AuthFields\`).\
> \
> \*\*Session mode\*\* (\`useEIP712\`, default \`false\`):\
> \- \`false\` = \*\*normal mode\*\* — secp256k1 request signature authenticates all requests including transactions.\
> &#x20; Session message includes the transaction consent line.\
> \- \`true\` = \*\*EIP-712 mode\*\* — secp256k1 request signature for reads; per-transaction EIP-712/ed25519 signature\
> &#x20; for transaction endpoints. Session message omits the consent line.\
> \
> \*\*Session message\*\* (the \`clientPublicKey\` line binds the secp256k1 key to the wallet signature):\
> \- Normal mode: \`"Authorize Hinkal session\nSession ID: \<sessionId>\nPublic Key: \<clientPublicKey>\nThis signature can also be used to submit transactions."\`\
> \- EIP-712 mode: \`"Authorize Hinkal session\nSession ID: \<sessionId>\nPublic Key: \<clientPublicKey>"\`\
> \
> \*\*EVM\*\*: sign message with EIP-191 \`personal\_sign\`.\
> \*\*Tron\*\*: sign with \`tronWeb.trx.signMessageV2\`.\
> \*\*Solana\*\*: sign UTF-8 message bytes with ed25519.<br>

```json
{"openapi":"3.0.3","info":{"title":"Hinkal API","version":"1.0.0"},"tags":[{"name":"Create Session"}],"servers":[{"url":"https://api.hinkal.io","description":"Production"}],"paths":{"/create-session":{"post":{"operationId":"createSession","summary":"Open an authentication session","description":"Registers a session for the caller's wallet using secp256k1 request signing.\n\n**Setup (all chains):**\n1. Generate a secp256k1 key pair on the client (32 random bytes → private key; derive compressed 33-byte public key).\n2. Send `clientPublicKey` (compressed secp256k1, 33 bytes = 66 hex chars) in the request body.\n3. Sign the raw request body with the secp256k1 private key (SHA-256 hash then compact ECDSA\n   signature) — no route binding. This is the only route not bound to a `\"<METHOD> <routePath>\"`\n   prefix, since no session exists yet to bind against.\n4. Include `x-hinkal-request-signature: <hex_compact_signature>` in request headers.\n5. Use the same key pair to authenticate all subsequent requests for this session — every\n   other route binds the signature to its own route path (see `AuthFields`).\n\n**Session mode** (`useEIP712`, default `false`):\n- `false` = **normal mode** — secp256k1 request signature authenticates all requests including transactions.\n  Session message includes the transaction consent line.\n- `true` = **EIP-712 mode** — secp256k1 request signature for reads; per-transaction EIP-712/ed25519 signature\n  for transaction endpoints. Session message omits the consent line.\n\n**Session message** (the `clientPublicKey` line binds the secp256k1 key to the wallet signature):\n- Normal mode: `\"Authorize Hinkal session\\nSession ID: <sessionId>\\nPublic Key: <clientPublicKey>\\nThis signature can also be used to submit transactions.\"`\n- EIP-712 mode: `\"Authorize Hinkal session\\nSession ID: <sessionId>\\nPublic Key: <clientPublicKey>\"`\n\n**EVM**: sign message with EIP-191 `personal_sign`.\n**Tron**: sign with `tronWeb.trx.signMessageV2`.\n**Solana**: sign UTF-8 message bytes with ed25519.\n","tags":["Create Session"],"parameters":[{"$ref":"#/components/parameters/XHinkalRequestSignatureCreateSession"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"signature":{"type":"string","description":"Chain-specific EIP-191 / ed25519 signature of the session message"},"address":{"type":"string","description":"Caller's wallet address (EVM/Tron hex address or Solana base58 public key)"},"sessionId":{"type":"string","format":"uuid","description":"Session identifier — a UUID you generate, also embedded in the signed message. Used to look up this session in all subsequent requests."},"nonce":{"type":"string","format":"uuid","description":"Per-request UUID. Echoed back in the response body."},"clientPublicKey":{"type":"string","description":"Compressed secp256k1 public key (33 bytes, hex-encoded = 66 characters). The enclave stores this key and uses it to verify the x-hinkal-request-signature header on all subsequent requests for this session."},"useEIP712":{"type":"boolean","default":false,"description":"When false (default), opens a normal mode session — secp256k1 request signature authorizes all requests. When true, opens an EIP-712 mode session — each transaction requires a per-transaction typed-data signature."},"expiresAt":{"type":"string","format":"date-time","description":"Optional ISO-8601 datetime at which the session should expire. Defaults to 24 hours from creation if omitted."}},"required":["signature","address","sessionId","nonce","clientPublicKey"]}}}},"responses":{"200":{"description":"Session created","headers":{},"content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"expiresAt":{"type":"string","format":"date-time","description":"ISO-8601 session expiry"},"nonce":{"type":"string","description":"Echoed per-request `nonce` from the request body."}},"required":["success","expiresAt","nonce"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Session ID already registered for a different owner.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}},"500":{"$ref":"#/components/responses/ServerError"}}}}},"components":{"parameters":{"XHinkalRequestSignatureCreateSession":{"name":"x-hinkal-request-signature","in":"header","required":true,"schema":{"type":"string"},"description":"Hex-encoded compact secp256k1 signature over the raw request body: `secp256k1_sign(SHA256(JSON.stringify(body)))`. This is the one route with no action binding — no session exists yet to bind against. Every other route binds the signature to its own `\"<METHOD> <routePath>\"`; see [Authentication](/enclave-api/authentication)."}},"responses":{"BadRequest":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}},"Unauthorized":{"description":"Invalid signature or reused nonce","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}},"ServerError":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}}},"schemas":{"FailedResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[false]},"error":{"type":"string"}},"required":["success","error"]}}}}
```
