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

# Get Setup Steps

> Post-deployment checklist with calldata for each outstanding step

Returns the authorization work a market still needs before it can lend, as an ordered checklist. Each incomplete step comes with ready-to-sign calldata and the role required to execute it.

The steps differ by collateral mode, because freeze markets and custody markets rely on different token-side permissions. Two steps are common to both.

## Path Parameters

<ParamField path="marketId" type="string" required>Market ID.</ParamField>

## Response Fields

<ResponseField name="data" type="object">
  <Expandable>
    <ResponseField name="complete" type="boolean">True when every step is done.</ResponseField>
    <ResponseField name="mode" type="string">`FREEZE` or `CUSTODY`. Determines which steps appear.</ResponseField>
    <ResponseField name="priceSource" type="string">`NAV` or `MARKET`.</ResponseField>
    <ResponseField name="collateralAgent" type="string">Named pledgee recorded at deployment.</ResponseField>
    <ResponseField name="liquidationRouterAddress" type="string">Router that must be made an eligible collateral recipient.</ResponseField>
    <ResponseField name="relayerAddress" type="string">The instance's registered wallet: the primary one, or the oldest verified wallet when no primary is set. Oracle signer and liquidator role checks are evaluated against this address. When null, the liquidator step can never report done.</ResponseField>

    <ResponseField name="steps" type="array">
      <Expandable>
        <ResponseField name="key" type="string">Step identifier.</ResponseField>
        <ResponseField name="title" type="string">Human-readable description.</ResponseField>
        <ResponseField name="done" type="boolean">Whether the on-chain state already satisfies this step.</ResponseField>
        <ResponseField name="requiredRole" type="string">Role the executing wallet must hold.</ResponseField>
        <ResponseField name="target" type="string">Contract the transaction is sent to.</ResponseField>
        <ResponseField name="subject" type="string">Address being authorized.</ResponseField>
        <ResponseField name="blocked" type="boolean">Present on the freeze adapter step only. `true` means the token cannot support freeze mode and the step is unachievable.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="calldata" type="object">Transactions for incomplete steps, keyed by step name, each `{ to, data, description }`. Completed steps are omitted.</ResponseField>
  </Expandable>
</ResponseField>

## Steps by Mode

**`FREEZE`**

| `key`                    | `requiredRole`            | Executed by                                                  |
| ------------------------ | ------------------------- | ------------------------------------------------------------ |
| `grantAdapterAgentRole`  | `TOKEN_AGENT_ADMIN`       | The collateral token's agent administrator                   |
| `verifyRouterOnRegistry` | `IDENTITY_REGISTRY_AGENT` | The token's identity registry operator                       |
| `authorizeOracleSigner`  | `ORACLE_OWNER`            | The oracle owner, which is the admin address from deployment |
| `grantLiquidatorRole`    | `DEFAULT_ADMIN_ROLE`      | The market admin                                             |

**`CUSTODY`**

| `key`                   | `requiredRole`            | Executed by                            |
| ----------------------- | ------------------------- | -------------------------------------- |
| `verifyAdapterAsHolder` | `IDENTITY_REGISTRY_AGENT` | The token's identity registry operator |
| `verifyRouterAsHolder`  | `IDENTITY_REGISTRY_AGENT` | The token's identity registry operator |
| `authorizeOracleSigner` | `ORACLE_OWNER`            | The oracle owner                       |
| `grantLiquidatorRole`   | `DEFAULT_ADMIN_ROLE`      | The market admin                       |

<Note>
  In `FREEZE` mode the router step has key `verifyRouterOnRegistry` but its calldata is emitted under `verifyRouterAsHolder`, matching the custody naming. Look up calldata by the `calldata` object's own keys rather than by step key.
</Note>

<Warning>
  The first two steps in either mode are executed by whoever administers the collateral token, which for an imported third-party security is the original issuer or their transfer agent, not Trusset and not necessarily you. Plan for that dependency before announcing a market.
</Warning>

<Tip>
  `grantLiquidatorRole` can be executed directly through [Set Liquidator Role](/endpoints/external-securities-lending/set-liquidator-role) when the registered wallet holds the market admin role.
</Tip>

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.trusset.org/lending-external-securities/api/markets/{marketId}/setup-steps" \
    -H "X-API-Key: trusset_your_key_here"
  ```

  ```typescript TypeScript theme={null}
  const res = await fetch(
    `https://api.trusset.org/lending-external-securities/api/markets/${marketId}/setup-steps`,
    { headers: { 'X-API-Key': 'trusset_your_key_here' } }
  );
  const { data } = await res.json();

  for (const step of data.steps.filter(s => !s.done)) {
    const tx = data.calldata[step.key] ?? data.calldata.verifyRouterAsHolder;
    console.log(`${step.title} requires ${step.requiredRole}`, tx);
  }
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "success": true,
    "data": {
      "mode": "FREEZE",
      "priceSource": "NAV",
      "collateralAgent": "0x555...666",
      "liquidationRouterAddress": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf",
      "relayerAddress": "0x123...456",
      "steps": [
        {
          "key": "grantAdapterAgentRole",
          "title": "Grant the freeze adapter the agent role on the token",
          "done": false,
          "requiredRole": "TOKEN_AGENT_ADMIN",
          "target": "0xabc...def",
          "subject": "0x4d2b...77ae",
          "blocked": false
        },
        {
          "key": "verifyRouterOnRegistry",
          "title": "Verify the market liquidation router on the identity registry",
          "done": false,
          "requiredRole": "IDENTITY_REGISTRY_AGENT",
          "target": "0x9e3c...1145",
          "subject": "0x067a3feea46649adad8e31c33b3a4d8774b8d8cf"
        },
        {
          "key": "authorizeOracleSigner",
          "title": "Authorize the issuer wallet as oracle price signer",
          "done": true,
          "requiredRole": "ORACLE_OWNER",
          "target": "0x3b25752c1459c5cf1b0bfcfdf0d56883c8047423",
          "subject": "0x123...456"
        },
        {
          "key": "grantLiquidatorRole",
          "title": "Grant LIQUIDATOR_ROLE to the issuer wallet",
          "done": false,
          "requiredRole": "DEFAULT_ADMIN_ROLE",
          "target": "0x70a0e25c7b768b87e658348b3b577678a173e038",
          "subject": "0x123...456"
        }
      ],
      "calldata": {
        "grantAdapterAgentRole": {
          "to": "0xabc...def",
          "data": "0x...",
          "description": "Grant agent role to freeze adapter 0x4d2b...77ae on the security token (requires token agent admin)"
        },
        "verifyRouterAsHolder": {
          "to": "0x9e3c...1145",
          "data": "0x...",
          "description": "Verify the market liquidation router as a holder on the identity registry"
        },
        "grantLiquidatorRole": {
          "to": "0x70a0e25c7b768b87e658348b3b577678a173e038",
          "data": "0x...",
          "description": "Grant LIQUIDATOR_ROLE to issuer wallet 0x123...456 (requires market DEFAULT_ADMIN_ROLE)"
        }
      },
      "complete": false
    }
  }
  ```
</ResponseExample>
