| Environment | URL |
|---|---|
| Testnet | https://dev.api.trustlesswork.com |
| Mainnet | https://api.trustlesswork.com |
All API requests require an API key in the Authorization header:
Authorization: Bearer YOUR_API_KEYGet an API Key: Contact Trustless Work or use the Backoffice dApp
Creates an escrow with one payout after all milestones approved.
POST /escrow/single-releaseHeaders:
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonRequest Body:
{
"engagementId": "order-12345",
"title": "Website Development",
"description": "Build marketing website with 3 pages",
"roles": {
"approver": "GCLIENT_WALLET...",
"serviceProvider": "GFREELANCER_WALLET...",
"releaseSigner": "GPLATFORM_WALLET...",
"platformAddress": "GPLATFORM_WALLET...",
"disputeResolver": "GRESOLVER_WALLET...",
"receiver": "GFREELANCER_WALLET..."
},
"amount": 1000,
"platformFee": 0.5,
"milestones": [
{
"description": "Homepage design",
"status": "Not Started",
"approved": false
},
{
"description": "Full deployment",
"status": "Not Started",
"approved": false
}
],
"trustline": {
"address": "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
"code": "USDC"
}
}Response:
{
"success": true,
"contractId": "CESCROW_ADDRESS...",
"escrow": {
"contractId": "CESCROW_ADDRESS...",
"engagementId": "order-12345",
"title": "Website Development",
"balance": 0,
"status": "created",
"flags": {
"disputed": false,
"released": false,
"resolved": false
}
}
}Creates an escrow with multiple payouts, one per milestone.
POST /escrow/multi-releaseRequest Body:
{
"engagementId": "grant-456",
"title": "Research Grant",
"description": "Funding project in phases",
"roles": {
"approver": "GDAO_WALLET...",
"serviceProvider": "GRESEARCHER_WALLET...",
"releaseSigner": "GDAO_TREASURY...",
"platformAddress": "GPLATFORM_WALLET...",
"disputeResolver": "GDAO_WALLET..."
},
"platformFee": 0.5,
"milestones": [
{
"description": "Interim report",
"amount": 500,
"status": "Not Started",
"flags": {
"approved": false,
"released": false,
"disputed": false,
"resolved": false
},
"receiver": "GRESEARCHER_WALLET..."
},
{
"description": "Final report",
"amount": 500,
"status": "Not Started",
"flags": {
"approved": false,
"released": false,
"disputed": false,
"resolved": false
},
"receiver": "GRESEARCHER_WALLET..."
}
],
"trustline": {
"address": "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
"code": "USDC"
}
}Response:
{
"success": true,
"contractId": "CESCROW_ADDRESS...",
"escrow": { /* ... */ },
"totalAmount": 1000
}Retrieve complete escrow information.
GET /escrow/{escrowId}Parameters:
escrowId(path): Contract ID / Escrow address
Response:
{
"contractId": "CESCROW_ADDRESS...",
"engagementId": "order-12345",
"title": "Website Development",
"description": "Build marketing website",
"balance": 1000,
"roles": { /* ... */ },
"milestones": [ /* ... */ ],
"flags": {
"disputed": false,
"released": false,
"resolved": false
},
"createdAt": "2026-03-11T10:00:00Z",
"updatedAt": "2026-03-11T11:30:00Z"
}Deposit funds into the escrow contract.
POST /escrow/{escrowId}/fundRequest Body:
{
"amount": 1000,
"depositorAddress": "GCLIENT_WALLET..."
}Response:
{
"success": true,
"transactionHash": "TX_HASH...",
"newBalance": 1000,
"status": "funded"
}Note: This generates a transaction that must be signed by the depositor's wallet (e.g., via Freighter).
Service Provider marks milestone progress.
POST /escrow/{escrowId}/milestone/{milestoneId}/updateParameters:
escrowId(path): Contract IDmilestoneId(path): Milestone index (0-based)
Request Body:
{
"status": "Complete",
"evidence": {
"url": "https://example.com/deliverable.pdf",
"description": "Final design with all revisions",
"timestamp": "2026-03-11T12:00:00Z"
}
}Response:
{
"success": true,
"milestone": {
"id": 0,
"description": "Homepage design",
"status": "Complete",
"approved": false,
"evidence": { /* ... */ }
}
}Approver validates milestone completion.
POST /escrow/{escrowId}/approveRequest Body (Single-Release):
{
"milestones": [0, 1] // Approve multiple milestones
}Request Body (Multi-Release):
{
"milestoneId": 0 // Approve specific milestone
}Response:
{
"success": true,
"approvedMilestones": [0, 1],
"readyForRelease": true
}Release Signer executes payout.
POST /escrow/{escrowId}/releaseRequest Body (Single-Release):
{
"releaseAll": true
}Request Body (Multi-Release):
{
"milestoneId": 0
}Response:
{
"success": true,
"transactionHash": "TX_HASH...",
"amountReleased": 992,
"platformFee": 5,
"protocolFee": 3,
"receiver": "GFREELANCER_WALLET..."
}Any authorized party can raise a dispute.
POST /escrow/{escrowId}/disputeRequest Body:
{
"reason": "Work not completed as agreed",
"evidence": "Screenshots, communication logs",
"requestedAction": "Full refund to client"
}Response:
{
"success": true,
"disputeId": "DISPUTE_123",
"status": "disputed",
"flags": {
"disputed": true,
"released": false,
"resolved": false
}
}Dispute Resolver arbitrates and executes decision.
POST /escrow/{escrowId}/dispute/{disputeId}/resolveRequest Body (Full Refund):
{
"action": "refund",
"percentage": 100,
"recipient": "GCLIENT_WALLET..."
}Request Body (Split):
{
"action": "split",
"distributions": [
{ "recipient": "GFREELANCER_WALLET...", "percentage": 60 },
{ "recipient": "GCLIENT_WALLET...", "percentage": 40 }
]
}Response:
{
"success": true,
"transactionHash": "TX_HASH...",
"resolution": "split",
"distributions": [ /* ... */ ],
"flags": {
"disputed": true,
"released": true,
"resolved": true
}
}Query escrows by various filters.
GET /escrowsQuery Parameters:
engagementId(optional): Filter by engagement IDstatus(optional): Filter by status (created,funded,released,disputed)role(optional): Filter by role addresslimit(optional): Results per page (default: 20)offset(optional): Pagination offset
Example:
GET /escrows?status=funded&limit=10Response:
{
"success": true,
"total": 42,
"escrows": [
{
"contractId": "CESCROW1...",
"engagementId": "order-123",
"title": "Website Dev",
"balance": 1000,
"status": "funded"
},
// ...
]
}All errors follow this format:
{
"success": false,
"error": {
"code": "INVALID_ROLE",
"message": "Approver address does not have required trustline",
"details": {
"address": "GINVALID...",
"requiredTrustline": "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5"
}
}
}Common Error Codes:
INVALID_ROLE: Role address invalid or missing trustlineINSUFFICIENT_BALANCE: Escrow balance too low for releaseUNAUTHORIZED: API key invalid or missing permissionsMILESTONE_NOT_APPROVED: Cannot release unapproved milestoneESCROW_ALREADY_RELEASED: Cannot modify released escrowDISPUTE_ACTIVE: Cannot release while dispute is active
| Tier | Requests/Minute | Requests/Day |
|---|---|---|
| Free | 60 | 5,000 |
| Pro | 300 | 50,000 |
| Enterprise | Custom | Custom |
Rate limit headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1678550400Subscribe to escrow events:
escrow.createdescrow.fundedmilestone.updatedmilestone.approvedescrow.releaseddispute.raiseddispute.resolved
npm install @trustless-work/sdkimport { TrustlessWorkSDK } from '@trustless-work/sdk';
const sdk = new TrustlessWorkSDK({
apiKey: 'YOUR_API_KEY',
network: 'testnet' // or 'mainnet'
});
// Create escrow
const escrow = await sdk.escrow.createSingleRelease({
engagementId: 'order-123',
title: 'Website Development',
// ...
});
// Fund escrow
await sdk.escrow.fund(escrow.contractId, {
amount: 1000,
depositorAddress: 'GCLIENT...'
});npm install @trustless-work/react-sdkimport { useCreateEscrow, useFundEscrow } from '@trustless-work/react-sdk';
function CreateEscrowForm() {
const { createEscrow, loading } = useCreateEscrow();
const handleSubmit = async () => {
const escrow = await createEscrow({
type: 'single-release',
// ...
});
};
return <form onSubmit={handleSubmit}>...</form>;
}Interactive API documentation with try-it-now functionality:
- Testnet: https://dev.api.trustlesswork.com/docs
- Mainnet: https://api.trustlesswork.com/docs
- See examples.md for complete integration examples
- See lifecycle-guide.md for when to call each endpoint
- Test on Testnet before going to Mainnet