Agreements – Retrieve User Agreements¶
When should I use this?¶
Use this flow whenever a signed-in user needs a consolidated list of agreements they created or joined: dashboards, recent activity views, or any post-login screen that must show ongoing deals, pending actions, or archived work.
Purpose¶
Expose the agreements visible to the authenticated user so clients can build list views, highlight pending obligations, and deep-link into agreement details without duplicating backend filtering logic. The endpoint returns PAYCIFI’s indexed agreement summaries and participant metadata; on-chain funding, validation, arbitration, and payout events settle independently on DShare and are reconciled asynchronously by the backend.
Preconditions¶
- A valid PAYCIFI session. The API inspects the optional
Authorization: Bearer <accessToken>header via thepopulateUsermiddleware and rejects malformed or expired tokens. - The
userIdpath parameter MUST belong to the authenticated user. The backend cross-checks the token and rejects any attempt to read another user’s agreements. - The user MUST be a participant (payer, provider, or arbitrator) in the agreements to see them; non-participant agreements are always excluded.
Client Responsibilities¶
- Ensure the
userIdin the request path matches the signed-in account; mismatches are rejected with an authorization error. - Supply role-aware UI hints (e.g., owner vs participant) based on
isOwner,selfParticipantType, anduserStatusfields returned by the API. - Cache or paginate results client-side if needed; the backend does not provide pagination parameters.
API Flow¶
- Request:
GET /api/v1/agreements/user/:userId?status=<optional>with an Authorization header. The optionalstatusquery must match anagreement_statuses.labelvalue (e.g.,pending,funded,completed). - Server visibility rules: The controller delegates to
AgreementsService.getAgreementsSummaryByUserId, which joinsparticipantsto keep only agreements whereuserIdappears in any role. Agreements the user archived viauser_agreement_preferences(is_archived = true) are automatically excluded, regardless of status. - Sorting & shaping: Results are ordered by
acceptance_deadlineascending and returned as summary objects containing: - Agreement metadata:
id,title,description,network,creationDate,currency,totalAmount,status,arbitrationStatus, deadlines. - Role context:
ownerUserId,isOwner,selfParticipantType,userStatus,providersEmails. - Payer snapshot: nested
payerobject (id,userId,name,email,phone,additionalInfo,status,owner). - Arbitrator name when present.
Example Request¶
GET /api/v1/agreements/user/3f6f6b4f-9c7d-4b9b-9f5a-43b0d4c2f101?status=pending
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Example Response¶
[
{
"id": "d9b6da1a-432c-47d8-8b0d-9ac01aa4f1ce",
"creationDate": "2025-01-04T11:22:03.145Z",
"title": "Design Sprint Retainer",
"description": "4-week design sprint with Nova Studio",
"network": "polygon",
"currency": "USDC",
"totalAmount": 12000,
"status": "pending",
"arbitrationStatus": null,
"acceptanceDeadline": 1736371200,
"completionDeadline": 1738972800,
"ownerUserId": "3f6f6b4f-9c7d-4b9b-9f5a-43b0d4c2f101",
"isOwner": true,
"selfParticipantType": "payer",
"userStatus": "pending",
"arbitratorName": null,
"providersEmails": [
"studio@nova.io"
],
"payer": {
"id": "f0629825-ea62-4a79-83e0-020b4b3f07c1",
"userId": "3f6f6b4f-9c7d-4b9b-9f5a-43b0d4c2f101",
"name": "Acme Corp",
"email": "payer@acme.com",
"phone": "+1-415-555-1212",
"additionalInfo": "Finance desk",
"participantType": "payer",
"owner": true,
"status": "pending"
}
},
{
"id": "9b7a9b7d-3341-4a8f-babc-2d0da1290333",
"creationDate": "2024-12-15T08:44:11.621Z",
"title": "Post-Production Package",
"description": "Footage cleanup and delivery",
"network": "ethereum",
"currency": "USDC",
"totalAmount": 4200,
"status": "funded",
"arbitrationStatus": "none",
"acceptanceDeadline": 1734556800,
"completionDeadline": 1737062400,
"ownerUserId": "a2d912c5-3de4-42cf-a306-1d8731e7f19a",
"isOwner": false,
"selfParticipantType": "provider",
"userStatus": "accepted",
"arbitratorName": "Global Escrow Partners",
"providersEmails": [
"studio@nova.io",
"sound@mixlab.fm"
],
"payer": {
"id": "a1304859-3c9a-49a0-8d3d-a8ae9e01d2ef",
"userId": "a2d912c5-3de4-42cf-a306-1d8731e7f19a",
"name": "Helios Ventures",
"email": "payables@helios.vc",
"phone": null,
"additionalInfo": null,
"participantType": "payer",
"owner": false,
"status": "funded"
}
}
]
Response Handling¶
- Empty array: The user is not part of any agreement (or archived all of them). Display a zero-state and allow creation or invitation flows.
- Partial visibility: Use
isOwnerandselfParticipantTypeto tailor what actions are surfaced. The API never exposes agreements where the user is not listed as a participant. - Navigation: Use the returned id to fetch full details via
GET /api/v1/agreements/:agreementId, and reference the Escrow Protocol documentation (/protocol/using-the-escrow/) for lifecycle rules, funding, and on-chain fund movement.
Error Codes¶
| HTTP | errorCode | When it occurs |
|---|---|---|
| 400 | missing-userId |
userId path parameter is absent. |
| 500 | agreements-retrieval-controller-error |
Unexpected failure inside the controller when fetching agreements. |
| 500 | agreementIds-retrieval-service-error |
Database failure while assembling the agreement summary. |
Related Endpoints¶
GET /api/v1/agreements/user/:userId— agreement summary list (this flow).GET /api/v1/agreements/:agreementId— full agreement detail for drill-down views.