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

# Get Enroll Signable Message (Stage 1)

> Stage 1 of the two-stage enrollment flow — returns a signable session-key message for the user to sign in their wallet.

Stage 1 of the two-stage enrollment flow. Validates that the `strategyId`
belongs to your tenant, peeks the user's next available account index, and
returns the signable message the user must sign plus the round-trip values
(`flowId`, `accountIndex`, `agentAccountId`) that stage 2
(`POST /v2/enroll`) will need.

Wallet addresses are exchanged as [CAIP-10](https://chainagnostic.org/CAIPs/caip-10)
account identifiers. For EVM, `ownerAccountId` and `agentAccountId` use the
chain-agnostic form `eip155:0:<address>` — a single wallet works on every
EIP-155 chain.

For EVM smart-contract wallets, pass `accountType: "ERC1271"` in both stages.
ERC-1271 enrollment returns an EIP-712 `typed-data` message and currently
requires exactly one EVM `chainId` per enrollment signature. Omit
`accountType` or pass `"ECDSA"` for the existing EOA/multichain path.

### Solana (SVM) enrollment

A Solana-native user enrolls with `ownerAccountId` set to a `solana:` CAIP-10
(`solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:<base58>`) and `chainIds: [1399811149]`.

The SVM flow mirrors how a Solana user joins the platform: the first portfolio
for a given **(tenant, user)** pair creates a **Swig smart wallet** (the user's
wallet key is its root authority — a Solana key for a `solana:` owner, an EVM
key for an `eip155:` owner; see below); subsequent portfolios **reuse the same
Swig**. Each portfolio is a **sub-account** of that Swig, and the sub-account
address is the **deposit address** the user funds. The pooled agent is attached
at create, so the portfolio is operable immediately.

#### Solana-rooted users (Model B)

Because creating the sub-account is an on-chain action, stage 1 returns a
**serialized Solana transaction** (`solanaTransaction`) for the user to sign with
their wallet — instead of signing `message`. The response also includes:

* `solanaTransaction` — base64 transaction; the user signs it and round-trips
  the signed bytes to `POST /v2/enroll` as `signedSolanaTransaction`. It carries
  a recent blockhash, so sign and submit promptly.
* `depositAccountId` — CAIP-10 of the sub-account the user sends funds to.
* `swigRoleId` — the Swig role that owns the sub-account (`1` for the first
  portfolio, higher when reusing an existing Swig).
* `reusedSwig` — `true` when an existing Swig PDA for this (tenant, user) is
  reused, `false` when a new one is created.

#### EVM-rooted users (Model A)

A user whose primary wallet is **EVM** enrolls into the same Solana sub-account
model by setting `ownerAccountId` to `eip155:0:<address>` with
`chainIds: [1399811149]`. Their secp256k1 (EVM) key becomes the Swig root.
Stage 1 returns the targets the client needs to build the authorization:

* `swigAccountId` — CAIP-10 of the parent Swig PDA.
* `depositAccountId` / `swigRoleId` / `reusedSwig` — as above.
* `agentAccountId`, `accountIndex`, `flowId` — round-tripped to stage 2.

The `message` is an `ecdsa` digest that is **informational only** — the user
does **not** sign it. The client builds a **slot-bound** Swig add-authority
payload (from `swigAccountId` + `agentAccountId` + a freshly captured slot),
`personal_sign`s its hash, then sends `userSecp256k1PublicKey` + `signature` +
`currentSlot` to `POST /v2/enroll`. Capture the slot and submit promptly — Swig
enforces a slot window. **There is no create-only fallback**; these fields are
required.

* Auth: `x-api-key` header (required)
* Scope: `enroll:write`

The returned `flowId` is the idempotency anchor for the matching
`POST /v2/enroll` call — it is valid for 24 hours. Re-submitting the same
`flowId` on stage 2 replays the cached response.

The `accountIndex` is **peeked, not reserved**: repeated stage-1 calls for
the same user return the same candidate index, and the index only advances
when stage 2 commits successfully. Retries, abandoned flows, and tests do
not burn account indices.

Unknown chains in `chainIds` are rejected with `400` before any enrollment
state is created — the allowed list is in the error `details`.

Common error responses:

* `400` when the request body is invalid, the `strategyId` doesn't exist or
  your API key cannot access it, or `chainIds` contains an unsupported chain
* `401` when `x-api-key` header is missing or the key is invalid
* `403` when the API key lacks the `enroll:write` scope
* `500` on unexpected server errors

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://api.glider.fi/v2/enroll/signature' \
    --header 'x-api-key: gldr_sk_your_api_key' \
    --header 'Content-Type: application/json' \
    --data '{
      "ownerAccountId": "eip155:0:0xabcdef0000000000000000000000000000000001",
      "strategyId": "01JWZEE2MF30KVRMRX53N88VA4",
      "chainIds": [1, 8453, 56],
      "accountType": "ECDSA"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://api.glider.fi/v2/enroll/signature", {
    method: "POST",
    headers: {
      "x-api-key": "gldr_sk_your_api_key",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      ownerAccountId: "eip155:0:0xabcdef0000000000000000000000000000000001",
      strategyId: "01JWZEE2MF30KVRMRX53N88VA4",
      chainIds: [1, 8453, 56],
      accountType: "ECDSA",
    }),
  });
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "success": true,
    "data": {
      "message": {
        "kind": "ecdsa",
        "raw": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
      },
      "agentAccountId": "eip155:0:0x1111111111111111111111111111111111111111",
      "accountIndex": "7",
      "accountType": "ECDSA",
      "flowId": "flow_abc123"
    }
  }
  ```

  ```json 200 (EVM / ERC-1271 smart-contract wallet) theme={null}
  {
    "success": true,
    "data": {
      "message": {
        "kind": "typed-data",
        "typedData": {
          "domain": {
            "name": "ERC1271Validator",
            "version": "0.0.1",
            "chainId": 1,
            "verifyingContract": "0x9999999999999999999999999999999999999999"
          },
          "types": {
            "MessageHash": [{ "name": "hash", "type": "bytes32" }]
          },
          "primaryType": "MessageHash",
          "message": {
            "hash": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
          }
        }
      },
      "agentAccountId": "eip155:0:0x1111111111111111111111111111111111111111",
      "accountIndex": "7",
      "accountType": "ERC1271",
      "flowId": "flow_abc123"
    }
  }
  ```

  ```json 200 (Solana / SVM subaccount) theme={null}
  {
    "success": true,
    "data": {
      "message": {
        "kind": "solana-message",
        "text": "Glider — enroll Solana portfolio\n..."
      },
      "agentAccountId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:Ag3nt...PdA",
      "accountIndex": "0",
      "flowId": "flow_abc123",
      "solanaTransaction": "AgAB... (base64; the user signs THIS)",
      "depositAccountId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:Dep0sit...PdA",
      "swigRoleId": 1,
      "reusedSwig": false
    }
  }
  ```

  ```json 200 (EVM-rooted / SVM subaccount) theme={null}
  {
    "success": true,
    "data": {
      "message": {
        "kind": "ecdsa",
        "raw": "0xdeadbeef... (informational — the user does NOT sign this)"
      },
      "agentAccountId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:Ag3nt...PdA",
      "accountIndex": "0",
      "flowId": "flow_abc123",
      "swigAccountId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:Sw1g...PdA",
      "depositAccountId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:Dep0sit...PdA",
      "swigRoleId": 1,
      "reusedSwig": false
    }
  }
  ```

  ```json 400 theme={null}
  {
    "success": false,
    "error": {
      "code": "API_400",
      "message": "Request validation failed",
      "details": [
        "chainIds: Unsupported chainId: [999]. Supported: [1, 8453, 42161, 56, 4663]"
      ]
    }
  }
  ```

  ```json 401 theme={null}
  {
    "success": false,
    "error": {
      "code": "API_101",
      "message": "Missing API key"
    }
  }
  ```

  ```json 403 theme={null}
  {
    "success": false,
    "error": {
      "code": "API_104",
      "message": "API key is missing required scope: enroll:write"
    }
  }
  ```
</ResponseExample>
