Skip to content

From credentials to your first signature

From operator-issued credentials to your first signature, in one pass.

Updated View as Markdown

This walks the shortest honest path to one working result: a signature produced by a key the service manages for you. It assumes your operator has already issued you a tenant API key and secret.

What you need

Set these once for the session. The API key and secret come from your operator — they are not self-service.

export API_URL=https://tee-api.hypetrade.xyz/v1
export API_KEY=your-api-key
export API_SECRET=your-api-secret

Create a workspace

A workspace is a password-protected container. Pick a slug and a strong password; you will need the password again to open it.

curl -X POST "$API_URL/workspaces" \
  -H "X-Api-Key: $API_KEY" \
  -H "X-Api-Secret: $API_SECRET" \
  -H "content-type: application/json" \
  -d '{"slug":"demo","password":"a-strong-workspace-password"}'

Slugs are lowercase letters, digits, and hyphens, must start alphanumeric, and run to 63 characters. A 201 returns the workspace record.

Mint a workspace token

This is the unlock. The token that comes back holds the workspace open, and its lifetime is the session.

curl -X POST "$API_URL/auth/token" \
  -H "X-Api-Key: $API_KEY" \
  -H "X-Api-Secret: $API_SECRET" \
  -H "content-type: application/json" \
  -d '{"workspace":"demo","password":"a-strong-workspace-password"}'
{
  "token": "eyJhbGciOi...",
  "expiresAt": "2026-08-18T12:34:56.000Z",
  "workspace": "demo",
  "scopes": ["read", "write", "sign"]
}

Capture the token — every remaining step uses it:

export TOKEN=the-token-value

Create an account

An HD account generates its own mnemonic. The mnemonic is never returned in a response body; generatedSecret: true only tells you one was created.

curl -X POST "$API_URL/accounts" \
  -H "Authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"displayName":"Treasury","kind":"HD"}'

The account slug is generated by the service, not chosen by you. It comes back at account.slug:

{
  "account": {
    "slug": "treasury-a1b2",
    "displayName": "Treasury",
    "kind": "HD",
    "locked": false,
    "defaultNetwork": "ethereum",
    "wallets": []
  }
}
export ACCOUNT=treasury-a1b2

Derive wallets

A new account starts empty. Derive wallets to get addresses.

curl -X POST "$API_URL/accounts/$ACCOUNT/wallets" \
  -H "Authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"count":2}'
{ "before": 0, "after": 2 }

Read the addresses

curl "$API_URL/accounts/$ACCOUNT/wallets" \
  -H "Authorization: Bearer $TOKEN"

Each wallet carries its addresses, one per VM. Each is fixed to the network the account was created with — see Accounts, wallets, and addresses:

{
  "wallets": [
    {
      "id": 1,
      "tags": [],
      "addresses": [
        { "publicKey": "0xabc…", "vm": "evm", "network": "ethereum", "chainId": 1 }
      ]
    }
  ]
}

Sign a message

Signing addresses a public key directly — you never walk account → wallet → address to sign. Resolution is scoped to your own workspace.

curl -X POST "$API_URL/sign/message" \
  -H "Authorization: Bearer $TOKEN" \
  -H "content-type: application/json" \
  -d '{"address":"0xabc…","message":"hello from tee-docker"}'
{ "address": "0xabc…", "signature": "0x…" }

Lock up when you are done

Revoking ends this token’s lease. It is the only token you minted here, so the workspace locks with it.

curl -X DELETE "$API_URL/auth/token" \
  -H "Authorization: Bearer $TOKEN"

What just happened

You used both credential tiers. Steps 1 and 2 used tenant credentials — the only two calls that do. Everything after used the workspace token, which carried the default read, write, and sign scopes.

Next

Navigation

Type to search…

↑↓ navigate↵ selectEsc close