> For the complete documentation index, see [llms.txt](https://developers.trooply.co.uk/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.trooply.co.uk/agreements.md).

# Agreements

## Get the current DPA template

> Returns the Data Protection Agreement template currently in force (full text, version and consent statement). A group's signable agreement is generated from this.

```json
{"openapi":"3.1.1","info":{"title":"Trooply API","version":"1.0"},"servers":[{"url":"https://api.trooply.co.uk/"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Bearer access token. Generate one from the **Developer** area of your Trooply account and send it as `Authorization: Bearer <token>`.","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"SuccessResponse":{"type":"object","properties":{"data":{},"meta":{"$ref":"#/components/schemas/ResponseMeta"}}},"ResponseMeta":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"request_id":{"type":"string","format":"uuid"},"total":{"type":"integer"}}},"Document":{"type":"object","properties":{"body":{"type":"string"},"consent_statement":{"type":"string"},"content_hash":{"type":"string"},"effective_from":{"type":"string","format":"date-time"},"id":{"type":"string","format":"uuid"},"jurisdiction":{"type":"string"},"title":{"type":"string"},"version":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ErrorDetail"}}},"ErrorDetail":{"type":"object","properties":{"code":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"},"status":{"type":"integer"}}}}},"paths":{"/v1/dpa/current":{"get":{"description":"Returns the Data Protection Agreement template currently in force (full text, version and consent statement). A group's signable agreement is generated from this.","tags":["agreements"],"summary":"Get the current DPA template","responses":{"200":{"description":"The current template","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Document"}}}]}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No template is currently published","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## List a group's agreements

> Returns every agreement recorded for the group, newest first, each with a short-lived download URL. A group may have many agreements over time but only one unsigned at once.

```json
{"openapi":"3.1.1","info":{"title":"Trooply API","version":"1.0"},"servers":[{"url":"https://api.trooply.co.uk/"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Bearer access token. Generate one from the **Developer** area of your Trooply account and send it as `Authorization: Bearer <token>`.","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"SuccessResponse":{"type":"object","properties":{"data":{},"meta":{"$ref":"#/components/schemas/ResponseMeta"}}},"ResponseMeta":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"request_id":{"type":"string","format":"uuid"},"total":{"type":"integer"}}},"Agreement":{"type":"object","properties":{"asset_id":{"description":"AssetID links the document in the asset system.","type":"string","format":"uuid"},"consent_statement":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string","format":"uuid"},"document_hash":{"description":"DocumentHash is the SHA-256 (hex) of the document bytes, pinning the exact\ncontent of this agreement.","type":"string"},"download_expires_at":{"description":"DownloadExpiresAt is when DownloadURL stops working.","type":"string","format":"date-time"},"download_url":{"description":"DownloadURL is a short-lived presigned URL to fetch the document; it is\ncomputed per response, not stored. Empty when generation is unconfigured.","type":"string"},"group_id":{"type":"string","format":"uuid"},"id":{"type":"string","format":"uuid"},"signed_at":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["unsigned","signed","void"]},"title":{"type":"string"},"type":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"version":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ErrorDetail"}}},"ErrorDetail":{"type":"object","properties":{"code":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"},"status":{"type":"integer"}}}}},"paths":{"/v1/groups/{group_id}/agreements":{"get":{"description":"Returns every agreement recorded for the group, newest first, each with a short-lived download URL. A group may have many agreements over time but only one unsigned at once.","tags":["agreements"],"summary":"List a group's agreements","parameters":[{"schema":{"type":"string","format":"uuid"},"description":"Group ID","name":"group_id","in":"path","required":true}],"responses":{"200":{"description":"The group's agreements","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Agreement"}}}}]}}}},"400":{"description":"group_id is not a valid UUID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Caller may not view this group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Generate a DPA agreement for a group

> Fills the DPA template with the supplied group name and address, renders it to a PDF, stores it as a private asset, and creates an unsigned agreement. The PDF is the canonical, hash-pinned document that gets signed. Fails with 409 if the group already has an unsigned agreement.

```json
{"openapi":"3.1.1","info":{"title":"Trooply API","version":"1.0"},"servers":[{"url":"https://api.trooply.co.uk/"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Bearer access token. Generate one from the **Developer** area of your Trooply account and send it as `Authorization: Bearer <token>`.","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"SuccessResponse":{"type":"object","properties":{"data":{},"meta":{"$ref":"#/components/schemas/ResponseMeta"}}},"ResponseMeta":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"request_id":{"type":"string","format":"uuid"},"total":{"type":"integer"}}},"Agreement":{"type":"object","properties":{"asset_id":{"description":"AssetID links the document in the asset system.","type":"string","format":"uuid"},"consent_statement":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string","format":"uuid"},"document_hash":{"description":"DocumentHash is the SHA-256 (hex) of the document bytes, pinning the exact\ncontent of this agreement.","type":"string"},"download_expires_at":{"description":"DownloadExpiresAt is when DownloadURL stops working.","type":"string","format":"date-time"},"download_url":{"description":"DownloadURL is a short-lived presigned URL to fetch the document; it is\ncomputed per response, not stored. Empty when generation is unconfigured.","type":"string"},"group_id":{"type":"string","format":"uuid"},"id":{"type":"string","format":"uuid"},"signed_at":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["unsigned","signed","void"]},"title":{"type":"string"},"type":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"version":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ErrorDetail"}}},"ErrorDetail":{"type":"object","properties":{"code":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"},"status":{"type":"integer"}}},"GenerateDPARequest":{"type":"object","required":["group_address","group_name"],"properties":{"group_address":{"type":"string","maxLength":1000,"minLength":1},"group_name":{"type":"string","maxLength":300,"minLength":1}}}}},"paths":{"/v1/groups/{group_id}/agreements/dpa":{"post":{"description":"Fills the DPA template with the supplied group name and address, renders it to a PDF, stores it as a private asset, and creates an unsigned agreement. The PDF is the canonical, hash-pinned document that gets signed. Fails with 409 if the group already has an unsigned agreement.","tags":["agreements"],"summary":"Generate a DPA agreement for a group","parameters":[{"schema":{"type":"string","format":"uuid"},"description":"Group ID","name":"group_id","in":"path","required":true}],"responses":{"201":{"description":"The created unsigned agreement","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Agreement"}}}]}}}},"400":{"description":"Malformed body or invalid UUID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Caller's role may not manage agreements","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"An unsigned agreement already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed, or the template is invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Document generation is not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateDPARequest"}}},"description":"Group name and address to fill in","required":true}}}}}
```

## Check whether a group has signed its DPA

> Reports whether the group has a signed Data Protection Agreement, and whether that signature covers the template version currently in force.

```json
{"openapi":"3.1.1","info":{"title":"Trooply API","version":"1.0"},"servers":[{"url":"https://api.trooply.co.uk/"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Bearer access token. Generate one from the **Developer** area of your Trooply account and send it as `Authorization: Bearer <token>`.","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"SuccessResponse":{"type":"object","properties":{"data":{},"meta":{"$ref":"#/components/schemas/ResponseMeta"}}},"ResponseMeta":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"request_id":{"type":"string","format":"uuid"},"total":{"type":"integer"}}},"DPAStatus":{"type":"object","properties":{"agreement_id":{"description":"AgreementID identifies the signed agreement, if any.","type":"string","format":"uuid"},"current_version":{"description":"CurrentVersion is the DPA template version currently in force, if published.","type":"string"},"signed":{"description":"Signed is true if the group has any signed DPA agreement.","type":"boolean"},"signed_at":{"description":"SignedAt is when the group last signed, if any.","type":"string","format":"date-time"},"signed_version":{"description":"SignedVersion is the version the group signed, if any.","type":"string"},"up_to_date":{"description":"UpToDate is true if the signed DPA matches the template version currently in\nforce. False when unsigned, or when only an older version was signed.","type":"boolean"}}},"ErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ErrorDetail"}}},"ErrorDetail":{"type":"object","properties":{"code":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"},"status":{"type":"integer"}}}}},"paths":{"/v1/groups/{group_id}/agreements/dpa/status":{"get":{"description":"Reports whether the group has a signed Data Protection Agreement, and whether that signature covers the template version currently in force.","tags":["agreements"],"summary":"Check whether a group has signed its DPA","parameters":[{"schema":{"type":"string","format":"uuid"},"description":"Group ID","name":"group_id","in":"path","required":true}],"responses":{"200":{"description":"The group's DPA status","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DPAStatus"}}}]}}}},"400":{"description":"group_id is not a valid UUID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Caller may not view this group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Get a single agreement

> Returns one agreement scoped to the group, including a short-lived download URL for its document.

```json
{"openapi":"3.1.1","info":{"title":"Trooply API","version":"1.0"},"servers":[{"url":"https://api.trooply.co.uk/"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Bearer access token. Generate one from the **Developer** area of your Trooply account and send it as `Authorization: Bearer <token>`.","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"SuccessResponse":{"type":"object","properties":{"data":{},"meta":{"$ref":"#/components/schemas/ResponseMeta"}}},"ResponseMeta":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"request_id":{"type":"string","format":"uuid"},"total":{"type":"integer"}}},"Agreement":{"type":"object","properties":{"asset_id":{"description":"AssetID links the document in the asset system.","type":"string","format":"uuid"},"consent_statement":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string","format":"uuid"},"document_hash":{"description":"DocumentHash is the SHA-256 (hex) of the document bytes, pinning the exact\ncontent of this agreement.","type":"string"},"download_expires_at":{"description":"DownloadExpiresAt is when DownloadURL stops working.","type":"string","format":"date-time"},"download_url":{"description":"DownloadURL is a short-lived presigned URL to fetch the document; it is\ncomputed per response, not stored. Empty when generation is unconfigured.","type":"string"},"group_id":{"type":"string","format":"uuid"},"id":{"type":"string","format":"uuid"},"signed_at":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["unsigned","signed","void"]},"title":{"type":"string"},"type":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"version":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ErrorDetail"}}},"ErrorDetail":{"type":"object","properties":{"code":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"},"status":{"type":"integer"}}}}},"paths":{"/v1/groups/{group_id}/agreements/{agreement_id}":{"get":{"description":"Returns one agreement scoped to the group, including a short-lived download URL for its document.","tags":["agreements"],"summary":"Get a single agreement","parameters":[{"schema":{"type":"string","format":"uuid"},"description":"Group ID","name":"group_id","in":"path","required":true},{"schema":{"type":"string","format":"uuid"},"description":"Agreement ID","name":"agreement_id","in":"path","required":true}],"responses":{"200":{"description":"The agreement","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Agreement"}}}]}}}},"400":{"description":"A path parameter is not a valid UUID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Caller may not view this group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such agreement for this group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Sign an agreement

> Records the group's signature of an unsigned agreement as an immutable, court-defensible event. Signer identity (id, email, role) is taken from the token, never the body. \`agreed\_hash\` must match the agreement's document hash; a mismatch returns 409.

```json
{"openapi":"3.1.1","info":{"title":"Trooply API","version":"1.0"},"servers":[{"url":"https://api.trooply.co.uk/"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Bearer access token. Generate one from the **Developer** area of your Trooply account and send it as `Authorization: Bearer <token>`.","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"SuccessResponse":{"type":"object","properties":{"data":{},"meta":{"$ref":"#/components/schemas/ResponseMeta"}}},"ResponseMeta":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"request_id":{"type":"string","format":"uuid"},"total":{"type":"integer"}}},"Signature":{"type":"object","properties":{"actor_ip":{"type":"string"},"actor_user_agent":{"type":"string"},"agreement_id":{"type":"string","format":"uuid"},"agreement_type":{"type":"string"},"agreement_version":{"type":"string"},"asset_id":{"type":"string","format":"uuid"},"checksum":{"type":"string"},"consent_statement":{"type":"string"},"document_hash":{"type":"string"},"executed_asset_id":{"description":"ExecutedAssetID / ExecutedDocumentHash reference the PAdES-signed \"executed\"\nPDF (agreement + certificate page + digital signature + timestamp). Null\nwhen PDF signing was not configured at signing time.","type":"string","format":"uuid"},"executed_document_hash":{"type":"string"},"executed_download_url":{"description":"ExecutedDownloadURL is a short-lived presigned URL to the signed PDF;\ncomputed per response, not stored.","type":"string"},"group_id":{"type":"string","format":"uuid"},"group_name":{"type":"string"},"id":{"type":"string","format":"uuid"},"request_id":{"type":"string"},"signed_at":{"type":"string","format":"date-time"},"signer_email":{"type":"string"},"signer_id":{"type":"string","format":"uuid"},"signer_name":{"type":"string"},"signer_role":{"type":"string"},"signer_title":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ErrorDetail"}}},"ErrorDetail":{"type":"object","properties":{"code":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"},"status":{"type":"integer"}}},"SignRequest":{"type":"object","required":["agreed_hash","signer_name"],"properties":{"accepted":{"description":"Accepted must be true: the affirmative act of agreement.","type":"boolean"},"agreed_hash":{"description":"AgreedHash must match the agreement's document hash, proving the signer saw\nthe exact document. A mismatch returns 409.","type":"string"},"signer_name":{"type":"string","maxLength":200,"minLength":1},"signer_title":{"type":"string","maxLength":200}}}}},"paths":{"/v1/groups/{group_id}/agreements/{agreement_id}/sign":{"post":{"description":"Records the group's signature of an unsigned agreement as an immutable, court-defensible event. Signer identity (id, email, role) is taken from the token, never the body. `agreed_hash` must match the agreement's document hash; a mismatch returns 409.","tags":["agreements"],"summary":"Sign an agreement","parameters":[{"schema":{"type":"string","format":"uuid"},"description":"Group ID","name":"group_id","in":"path","required":true},{"schema":{"type":"string","format":"uuid"},"description":"Agreement ID","name":"agreement_id","in":"path","required":true}],"responses":{"201":{"description":"The recorded signature","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Signature"}}}]}}}},"400":{"description":"Malformed body, invalid UUID, or not accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Caller's role may not sign agreements","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Already signed, not unsigned, or document changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed; see error.fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignRequest"}}},"description":"Signature","required":true}}}}}
```

## Get an agreement's signature

> Returns the immutable signature evidence recorded when the agreement was signed.

```json
{"openapi":"3.1.1","info":{"title":"Trooply API","version":"1.0"},"servers":[{"url":"https://api.trooply.co.uk/"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Bearer access token. Generate one from the **Developer** area of your Trooply account and send it as `Authorization: Bearer <token>`.","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"SuccessResponse":{"type":"object","properties":{"data":{},"meta":{"$ref":"#/components/schemas/ResponseMeta"}}},"ResponseMeta":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"request_id":{"type":"string","format":"uuid"},"total":{"type":"integer"}}},"Signature":{"type":"object","properties":{"actor_ip":{"type":"string"},"actor_user_agent":{"type":"string"},"agreement_id":{"type":"string","format":"uuid"},"agreement_type":{"type":"string"},"agreement_version":{"type":"string"},"asset_id":{"type":"string","format":"uuid"},"checksum":{"type":"string"},"consent_statement":{"type":"string"},"document_hash":{"type":"string"},"executed_asset_id":{"description":"ExecutedAssetID / ExecutedDocumentHash reference the PAdES-signed \"executed\"\nPDF (agreement + certificate page + digital signature + timestamp). Null\nwhen PDF signing was not configured at signing time.","type":"string","format":"uuid"},"executed_document_hash":{"type":"string"},"executed_download_url":{"description":"ExecutedDownloadURL is a short-lived presigned URL to the signed PDF;\ncomputed per response, not stored.","type":"string"},"group_id":{"type":"string","format":"uuid"},"group_name":{"type":"string"},"id":{"type":"string","format":"uuid"},"request_id":{"type":"string"},"signed_at":{"type":"string","format":"date-time"},"signer_email":{"type":"string"},"signer_id":{"type":"string","format":"uuid"},"signer_name":{"type":"string"},"signer_role":{"type":"string"},"signer_title":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ErrorDetail"}}},"ErrorDetail":{"type":"object","properties":{"code":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"},"status":{"type":"integer"}}}}},"paths":{"/v1/groups/{group_id}/agreements/{agreement_id}/signature":{"get":{"description":"Returns the immutable signature evidence recorded when the agreement was signed.","tags":["agreements"],"summary":"Get an agreement's signature","parameters":[{"schema":{"type":"string","format":"uuid"},"description":"Group ID","name":"group_id","in":"path","required":true},{"schema":{"type":"string","format":"uuid"},"description":"Agreement ID","name":"agreement_id","in":"path","required":true}],"responses":{"200":{"description":"The signature record","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Signature"}}}]}}}},"400":{"description":"A path parameter is not a valid UUID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Caller may not view this group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Agreement not found, or not yet signed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Verify an agreement's signature

> Recomputes the signature checksum from its stored fields and re-hashes the signed document, confirming the record and the document are unaltered. Read-only.

```json
{"openapi":"3.1.1","info":{"title":"Trooply API","version":"1.0"},"servers":[{"url":"https://api.trooply.co.uk/"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Bearer access token. Generate one from the **Developer** area of your Trooply account and send it as `Authorization: Bearer <token>`.","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"SuccessResponse":{"type":"object","properties":{"data":{},"meta":{"$ref":"#/components/schemas/ResponseMeta"}}},"ResponseMeta":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"request_id":{"type":"string","format":"uuid"},"total":{"type":"integer"}}},"VerificationResult":{"type":"object","properties":{"agreement_id":{"type":"string","format":"uuid"},"checksum_valid":{"description":"ChecksumValid is true if the checksum recomputed from the stored signature\nfields matches the stored checksum.","type":"boolean"},"document_intact":{"description":"DocumentIntact is true if re-hashing the stored document reproduces the\nhash recorded at signing (the document has not been tampered with).","type":"boolean"},"document_resolved":{"description":"DocumentResolved is true if the signed document bytes could be read back.","type":"boolean"},"executed_document_intact":{"description":"ExecutedDocumentIntact is true if the stored signed PDF still matches the\nhash recorded at signing.","type":"boolean"},"executed_present":{"description":"ExecutedPresent is true if a PAdES-signed executed PDF was recorded.","type":"boolean"},"notes":{"description":"Notes carries human-readable detail for each failed check.","type":"array","items":{"type":"string"}},"signature_id":{"type":"string","format":"uuid"},"valid":{"description":"Valid is true only if every check below passed.","type":"boolean"}}},"ErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ErrorDetail"}}},"ErrorDetail":{"type":"object","properties":{"code":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"},"status":{"type":"integer"}}}}},"paths":{"/v1/groups/{group_id}/agreements/{agreement_id}/verify":{"get":{"description":"Recomputes the signature checksum from its stored fields and re-hashes the signed document, confirming the record and the document are unaltered. Read-only.","tags":["agreements"],"summary":"Verify an agreement's signature","parameters":[{"schema":{"type":"string","format":"uuid"},"description":"Group ID","name":"group_id","in":"path","required":true},{"schema":{"type":"string","format":"uuid"},"description":"Agreement ID","name":"agreement_id","in":"path","required":true}],"responses":{"200":{"description":"The verification result","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/VerificationResult"}}}]}}}},"400":{"description":"A path parameter is not a valid UUID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Caller may not view this group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Agreement not found, or not yet signed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Void an unsigned agreement

> Voids an unsigned agreement so a fresh one can be generated. Only an unsigned agreement can be voided.

```json
{"openapi":"3.1.1","info":{"title":"Trooply API","version":"1.0"},"servers":[{"url":"https://api.trooply.co.uk/"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Bearer access token. Generate one from the **Developer** area of your Trooply account and send it as `Authorization: Bearer <token>`.","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"SuccessResponse":{"type":"object","properties":{"data":{},"meta":{"$ref":"#/components/schemas/ResponseMeta"}}},"ResponseMeta":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"request_id":{"type":"string","format":"uuid"},"total":{"type":"integer"}}},"Agreement":{"type":"object","properties":{"asset_id":{"description":"AssetID links the document in the asset system.","type":"string","format":"uuid"},"consent_statement":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string","format":"uuid"},"document_hash":{"description":"DocumentHash is the SHA-256 (hex) of the document bytes, pinning the exact\ncontent of this agreement.","type":"string"},"download_expires_at":{"description":"DownloadExpiresAt is when DownloadURL stops working.","type":"string","format":"date-time"},"download_url":{"description":"DownloadURL is a short-lived presigned URL to fetch the document; it is\ncomputed per response, not stored. Empty when generation is unconfigured.","type":"string"},"group_id":{"type":"string","format":"uuid"},"id":{"type":"string","format":"uuid"},"signed_at":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["unsigned","signed","void"]},"title":{"type":"string"},"type":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"version":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ErrorDetail"}}},"ErrorDetail":{"type":"object","properties":{"code":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"},"status":{"type":"integer"}}}}},"paths":{"/v1/groups/{group_id}/agreements/{agreement_id}/void":{"post":{"description":"Voids an unsigned agreement so a fresh one can be generated. Only an unsigned agreement can be voided.","tags":["agreements"],"summary":"Void an unsigned agreement","parameters":[{"schema":{"type":"string","format":"uuid"},"description":"Group ID","name":"group_id","in":"path","required":true},{"schema":{"type":"string","format":"uuid"},"description":"Agreement ID","name":"agreement_id","in":"path","required":true}],"responses":{"200":{"description":"The voided agreement","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Agreement"}}}]}}}},"400":{"description":"A path parameter is not a valid UUID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Caller's role may not manage agreements","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such agreement for this group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Agreement is not unsigned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers.trooply.co.uk/agreements.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
