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

# Governance Read Endpoints

> Read a token's governance config, its proposals, the connected user's votes, and the voter list for a single proposal. No scope required.

Governance reads mirror public on-chain state, so any valid access token may call them.

|                |              |
| -------------- | ------------ |
| **Scope**      | None         |
| **Rate limit** | 300 / minute |

## GET /partner/v1/governance/{mint}

Returns everything needed to render a governance UI in a single call.

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.tren.ch/partner/v1/governance/$MINT" \
    -H "Authorization: Bearer $ACCESS_TOKEN"
  ```

  ```javascript Node.js theme={null}
  const res = await fetch(`https://api.tren.ch/partner/v1/governance/${mint}`, {
    headers: { Authorization: `Bearer ${accessToken}` },
  });

  const { governance, proposals, viewerVotes } = await res.json();
  ```

  ```python Python theme={null}
  import requests

  res = requests.get(
    f"https://api.tren.ch/partner/v1/governance/{mint}",
    headers={"Authorization": f"Bearer {access_token}"},
  )

  data = res.json()
  ```
</CodeGroup>

If the token has no governance account, the endpoint returns `404 governance_not_found`.

### Response

```json theme={null}
{
  "governance": { "…": "…" },
  "proposals": [ { "…": "…" } ],
  "viewerVotes": [ { "…": "…" } ]
}
```

Up to 100 proposals are returned, newest first.

<Warning>
  That 100 is a hard ceiling rather than a page. There is no cursor, offset, or `limit` parameter on this endpoint, so a governance with more than 100 proposals will return the newest 100 with no way to reach the rest through the Partner API. We recommend building on the assumption that older proposals may be unreachable.
</Warning>

### The Governance Object

| Field                       | Type    | Meaning                                           |
| --------------------------- | ------- | ------------------------------------------------- |
| `governance`                | string  | Governance account address                        |
| `mint`                      | string  | Token mint                                        |
| `metadata`                  | string  | Metadata account address                          |
| `creator`                   | string  | Wallet that launched the token                    |
| `totalSupply`               | string  | Total supply in base units                        |
| `createdAtUnix`             | string  | Governance creation time                          |
| `mutableUntilUnix`          | string  | When metadata locks permanently                   |
| `minVoterCount`             | number  | Distinct voters required for a valid vote         |
| `minLockAmount`             | string  | Smallest accepted vote, in base units             |
| `minParticipatingSupplyBps` | number  | Share of supply that must vote, in basis points   |
| `approvalBps`               | number  | Yes-share required to pass, in basis points       |
| `proposalBondBps`           | number  | Bond a proposer locks, in basis points of supply  |
| `finalized`                 | boolean | Metadata locked forever by governance vote        |
| `contentRevision`           | string  | Increments on every applied metadata change       |
| `mutabilityExtended`        | boolean | Whether the window has already been extended once |
| `nameLocked`                | boolean | Field permanently locked                          |
| `symbolLocked`              | boolean | Field permanently locked                          |
| `imageLocked`               | boolean | Field permanently locked                          |
| `descriptionLocked`         | boolean | Field permanently locked                          |
| `websiteLocked`             | boolean | Field permanently locked                          |
| `twitterLocked`             | boolean | Field permanently locked                          |
| `telegramLocked`            | boolean | Field permanently locked                          |

<Note>
  We recommend checking the per-field `*Locked` flags before offering an edit. A proposal that touches a locked field fails at build time rather than at vote time, so filtering the UI up front saves the user a wasted bond.
</Note>

### The Proposal Object

| Field                     | Type           | Meaning                                      |
| ------------------------- | -------------- | -------------------------------------------- |
| `proposal`                | string         | Proposal account address                     |
| `governance`              | string         | Parent governance account                    |
| `proposer`                | string         | Wallet that created it                       |
| `proposalIndex`           | string         | Monotonic index within the governance        |
| `baseContentRevision`     | string         | Revision this proposal was authored against  |
| `actionKind`              | string         | What the proposal does                       |
| `actionName`              | string \| null | Proposed new name                            |
| `actionSymbol`            | string \| null | Proposed new symbol                          |
| `actionUri`               | string \| null | Proposed new metadata URI                    |
| `actionAdditionalSeconds` | string \| null | Requested mutability extension               |
| `changedName`             | boolean        | Whether this field is part of the change set |
| `changedSymbol`           | boolean        | Whether this field is part of the change set |
| `changedImage`            | boolean        | Whether this field is part of the change set |
| `changedDescription`      | boolean        | Whether this field is part of the change set |
| `changedWebsite`          | boolean        | Whether this field is part of the change set |
| `changedTwitter`          | boolean        | Whether this field is part of the change set |
| `changedTelegram`         | boolean        | Whether this field is part of the change set |
| `createdAtUnix`           | string         | Creation time                                |
| `votingEndsAtUnix`        | string         | When voting closes                           |
| `proposalBondAmount`      | string         | Tokens locked as bond                        |
| `proposalBondWithdrawn`   | boolean        | Whether the bond was reclaimed               |
| `yesVotes`                | string         | Yes weight in base units                     |
| `noVotes`                 | string         | No weight in base units                      |
| `participatingSupply`     | string         | Total weight cast                            |
| `participatingVoters`     | number         | Distinct qualifying voters                   |
| `outcome`                 | string         | Result once settled                          |
| `executed`                | boolean        | Whether the action was applied on-chain      |
| `settled`                 | boolean        | Whether the proposal has been settled        |
| `metadataUpdated`         | boolean        | Whether metadata actually changed            |
| `signature`               | string         | Creating transaction                         |
| `blockTime`               | string         | ISO 8601 timestamp                           |

<Warning>
  The `baseContentRevision` field is how Trench detects edit conflicts. If the token's `contentRevision` advanced after a proposal was authored, that proposal is stale, and building another against the old revision fails with `stale_content_revision`.
</Warning>

### viewerVotes

This array contains the connected user's own votes, derived from the access token rather than a caller-supplied address, so you can render whether a user has voted without making a second request. Each entry has the same shape as the vote objects described below.

## GET /partner/v1/governance/proposals/{proposal}/votes

Returns the voters on a single proposal, largest stake first.

| Parameter | In    | Default | Max   |
| --------- | ----- | ------- | ----- |
| `limit`   | query | `50`    | `200` |

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.tren.ch/partner/v1/governance/proposals/$PROPOSAL/votes?limit=50" \
    -H "Authorization: Bearer $ACCESS_TOKEN"
  ```

  ```javascript Node.js theme={null}
  const res = await fetch(
    `https://api.tren.ch/partner/v1/governance/proposals/${proposal}/votes?limit=50`,
    { headers: { Authorization: `Bearer ${accessToken}` } }
  );

  const { votes } = await res.json();
  ```

  ```python Python theme={null}
  import requests

  res = requests.get(
    f"https://api.tren.ch/partner/v1/governance/proposals/{proposal}/votes",
    params={"limit": 50},
    headers={"Authorization": f"Bearer {access_token}"},
  )

  votes = res.json()["votes"]
  ```
</CodeGroup>

<Note>
  The `limit` parameter fails soft. A value that is not a positive number, such as `0`, `abc`, or an empty string, is silently treated as `50` rather than rejected, and anything above `200` is clamped down. Since you will never receive a `400` from this parameter, we recommend validating it yourself if the value comes from user input.

  As with proposals, there is no cursor, so a proposal with more than 200 voters cannot be fully enumerated here.
</Note>

<Note>
  The `{mint}` and `{proposal}` path segments are not checked for Base58 validity before the lookup runs. A malformed address returns `404 governance_not_found` or an empty `votes` array rather than `400 invalid_input`, so an empty result is not evidence that the address was well-formed.
</Note>

### Response

```json theme={null}
{
  "votes": [
    {
      "proposal": "…",
      "voter": "…",
      "side": "yes",
      "amount": "1000000",
      "countedAsVoter": true,
      "active": true,
      "withdrawn": false,
      "signature": "…",
      "blockTime": "2026-07-25T21:49:05.000Z"
    }
  ]
}
```

| Field            | Type    | Meaning                                         |
| ---------------- | ------- | ----------------------------------------------- |
| `voter`          | string  | Voting wallet                                   |
| `side`           | string  | `yes` or `no`                                   |
| `amount`         | string  | Locked weight in base units                     |
| `countedAsVoter` | boolean | Whether this vote counts toward `minVoterCount` |
| `active`         | boolean | False once cancelled                            |
| `withdrawn`      | boolean | Whether locked tokens were reclaimed            |
| `signature`      | string  | Voting transaction                              |
| `blockTime`      | string  | ISO 8601 timestamp                              |

<Note>
  A vote can have `countedAsVoter: false` while still carrying weight, because votes below `minLockAmount` contribute to the tally but not to the distinct-voter quorum. We recommend displaying `participatingVoters` from the proposal rather than counting this array.
</Note>

## Errors

| Status | Error                  | Cause                              |
| ------ | ---------------------- | ---------------------------------- |
| `401`  | `invalid_token`        | Missing, expired, or revoked token |
| `404`  | `governance_not_found` | Token has no governance account    |
