> For the complete documentation index, see [llms.txt](https://docs.trustlesswork.com/trustless-work/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.trustlesswork.com/trustless-work/v2-en/api-rest/escrow-information/get-escrow-milestones.md).

# Get Escrow Milestones

Read the milestones of one escrow or a batch.

### **Headers**

<table><thead><tr><th width="366">Name</th><th>Value</th></tr></thead><tbody><tr><td>Content-Type</td><td><code>application/json</code></td></tr><tr><td>x-api-key</td><td><code>&#x3C;token></code></td></tr></tbody></table>

### Open API

## GET /escrows/{contractId}/milestones

## Read one escrow’s milestones only

> Addressed by the on-chain contract address (C…). Returns the milestone slice of the projected state without the rest of the detail payload — entry shape depends on the contract flavor. Returns 404 only if the escrow is unknown on this network.

```json
{"openapi":"3.0.0","info":{"title":"👋🏼 Trustless Work Core API — All Endpoints (Unified)","version":"1.0"},"servers":[{"url":"https://beta.api.trustlesswork.com"}],"security":[{}],"paths":{"/escrows/{contractId}/milestones":{"get":{"description":"Addressed by the on-chain contract address (C…). Returns the milestone slice of the projected state without the rest of the detail payload — entry shape depends on the contract flavor. Returns 404 only if the escrow is unknown on this network.","operationId":"EscrowQueryController_milestones","parameters":[{"name":"contractId","required":true,"in":"path","description":"On-chain escrow contract address (C…, 56 chars).","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscrowMilestonesResponse"}}}},"400":{"description":"Request body or query params fail schema validation (wrong type, missing required field, unknown property).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsResponseDto"}}}},"401":{"description":"Missing, malformed, expired, revoked or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsResponseDto"}}}},"403":{"description":"API key is valid but does not have the role required for this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsResponseDto"}}}},"404":{"description":"Escrow not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsResponseDto"}}}},"422":{"description":"Payload is well-formed but a business rule rejects it (e.g. amount out of range, role not allowed for this user).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsResponseDto"}}}}},"summary":"Read one escrow’s milestones only","tags":["Escrows"]}}},"components":{"schemas":{"EscrowMilestonesResponse":{"type":"object","properties":{"contractId":{"type":"string","description":"On-chain escrow contract (C...)."},"type":{"type":"string","description":"Detected contract flavor. Null until the first state.","nullable":true},"milestones":{"description":"Raw milestone entries from the projected state (shape depends on the contract flavor). Empty until the first state is projected.","additionalProperties":true,"type":"array","items":{"type":"object"}}},"required":["contractId","milestones"]},"ProblemDetailsResponseDto":{"type":"object","properties":{"type":{"type":"string","description":"Stable URI identifying the error type. Hash-link points to the docs."},"title":{"type":"string","description":"Short human-readable summary of the problem."},"status":{"type":"number","description":"HTTP status code, repeated here for typed clients."},"code":{"type":"string","description":"Machine-readable error code. Stable across versions; safe to switch on."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"URI of the request that triggered the error."},"traceId":{"type":"string","description":"Correlation id propagated from the `X-Trace-Id` header (or generated). Use it when contacting support to reference a specific request."},"extensions":{"type":"object","description":"Optional structured context. Shape depends on the error code; documented per-endpoint when relevant.","additionalProperties":true}},"required":["type","title","status","code","detail"]}}}}
```

Reads one escrow's milestones only — a lighter call than fetching the whole escrow.

| Name       | Type   | In   | Description                    |
| ---------- | ------ | ---- | ------------------------------ |
| contractId | string | path | On-chain escrow address (`C…`) |

## GET /escrows/milestones

## Read the milestones of a batch of escrows

> Bulk companion of \`GET /escrows/:contractId/milestones\`: pass up to 50 contract addresses (\`contractIds=C…\&contractIds=C…\`) and get the milestone slice of each. Unknown ids are silently absent from the response.

```json
{"openapi":"3.0.0","info":{"title":"👋🏼 Trustless Work Core API — All Endpoints (Unified)","version":"1.0"},"servers":[{"url":"https://beta.api.trustlesswork.com"}],"security":[{}],"paths":{"/escrows/milestones":{"get":{"description":"Bulk companion of `GET /escrows/:contractId/milestones`: pass up to 50 contract addresses (`contractIds=C…&contractIds=C…`) and get the milestone slice of each. Unknown ids are silently absent from the response.","operationId":"EscrowQueryController_milestonesBatch","parameters":[{"name":"contractIds","required":true,"in":"query","description":"On-chain contract addresses (repeat the param: `contractIds=C…&contractIds=C…`, 1–50). Inaccessible or unknown ids are silently absent from the response.","schema":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscrowMilestonesListResponse"}}}},"400":{"description":"Request body or query params fail schema validation (wrong type, missing required field, unknown property).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsResponseDto"}}}},"401":{"description":"Missing, malformed, expired, revoked or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsResponseDto"}}}},"403":{"description":"API key is valid but does not have the role required for this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsResponseDto"}}}},"422":{"description":"Payload is well-formed but a business rule rejects it (e.g. amount out of range, role not allowed for this user).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsResponseDto"}}}}},"summary":"Read the milestones of a batch of escrows","tags":["Escrows"]}}},"components":{"schemas":{"EscrowMilestonesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EscrowMilestonesResponse"}}},"required":["data"]},"EscrowMilestonesResponse":{"type":"object","properties":{"contractId":{"type":"string","description":"On-chain escrow contract (C...)."},"type":{"type":"string","description":"Detected contract flavor. Null until the first state.","nullable":true},"milestones":{"description":"Raw milestone entries from the projected state (shape depends on the contract flavor). Empty until the first state is projected.","additionalProperties":true,"type":"array","items":{"type":"object"}}},"required":["contractId","milestones"]},"ProblemDetailsResponseDto":{"type":"object","properties":{"type":{"type":"string","description":"Stable URI identifying the error type. Hash-link points to the docs."},"title":{"type":"string","description":"Short human-readable summary of the problem."},"status":{"type":"number","description":"HTTP status code, repeated here for typed clients."},"code":{"type":"string","description":"Machine-readable error code. Stable across versions; safe to switch on."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"URI of the request that triggered the error."},"traceId":{"type":"string","description":"Correlation id propagated from the `X-Trace-Id` header (or generated). Use it when contacting support to reference a specific request."},"extensions":{"type":"object","description":"Optional structured context. Shape depends on the error code; documented per-endpoint when relevant.","additionalProperties":true}},"required":["type","title","status","code","detail"]}}}}
```

The batch version: milestones for several escrows at once.

| Name        | Type      | In    | Description                      |
| ----------- | --------- | ----- | -------------------------------- |
| contractIds | string\[] | query | 1–50 addresses. Repeat the param |

### **What this Endpoint returns?**

The milestone list of each escrow, including `status` and the `approvals { target, approvalCount, approvedBy }` progress used to render approval state.

The batch endpoint is **not paginated** — the request itself is bounded at 50 ids. Unknown ids are silently absent rather than an error, so check what came back.

### Use Example:

```typescript
import axios from "axios";

const http = axios.create({
  baseURL: "https://beta.api.trustlesswork.com",
  timeout: 10000,
  headers: {
    "Content-Type": "application/json",
    "x-api-key": your_api_key,
  },
});

export const useExample = async (contractId: string) => {
  // One escrow
  const one = await http.get(`/escrows/${contractId}/milestones`);

  // Several at once
  const params = new URLSearchParams();
  ["CXYZ...", "CABC..."].forEach(id => params.append("contractIds", id));
  const many = await http.get(`/escrows/milestones?${params.toString()}`);

  return { one: one.data, many: many.data };
}
```

{% hint style="info" %}
These reads come from the read-model, which is eventually consistent. Right after submitting a transaction a `404` usually means "not projected yet", not "does not exist" — poll briefly instead of treating it as an error.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.trustlesswork.com/trustless-work/v2-en/api-rest/escrow-information/get-escrow-milestones.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
