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

# Downloading certificates & agreements

> Retrieve the Certificate of Acceptance, Clickwrap Agreement PDFs, and accepted content via the API and SDK.

<Note>
  **Prerequisites:** A [verified clickwrap event](/dev/guides/verifying-signature) with status `ACCEPTED`, and your [App ID + App Key](/product/integrations/integrations-overview) for server-side calls.
</Note>

After a clickwrap event is verified with status `ACCEPTED`, ClickTerm generates downloadable PDF documents and stores the accepted content. Use these endpoints to retrieve them for legal records, compliance audits, or customer portals.

<Tip>
  **Don't have a `clickwrapEventId`?** See [`GET /clickwrap-events`](/api-reference/events/list-clickwrap-events) in the API reference.
</Tip>

## Certificate of Acceptance

A digitally signed PDF that proves a specific user accepted a specific clickwrap version at a specific time. Includes user ID, timestamp, IP address, browser/device information. Stored in immutable storage at the time of event verification and serves as admissible proof in legal and compliance contexts.

### Endpoint

```
GET https://api.clickterm.com/public-client/v1/clickwrap-events/{clickwrapEventId}/certificate
```

| Parameter          | Required | Description                                                                                          |
| ------------------ | -------- | ---------------------------------------------------------------------------------------------------- |
| `clickwrapEventId` | Yes      | The identifier for the Clickwrap Event from which you want to retrieve the Certificate of Acceptance |

<CodeGroup>
  ```java example.java (Java) theme={null}
  HttpResponse<InputStream> response = Unirest.get(
      "https://api.clickterm.com/public-client/v1/clickwrap-events/" + clickwrapEventId + "/certificate")
    .header("X-APP-ID", "YOUR_APP_ID")
    .header("X-APP-KEY", "YOUR_APP_KEY")
    .asBinary();
  Files.copy(response.getBody(), Path.of("certificate.pdf"));
  ```

  ```javascript example.js (Node.js) theme={null}
  const response = await fetch(
    `https://api.clickterm.com/public-client/v1/clickwrap-events/${eventId}/certificate`,
    {
      headers: {
        "X-APP-ID": process.env.CLICKTERM_APP_ID,
        "X-APP-KEY": process.env.CLICKTERM_APP_KEY,
      },
    }
  );
  const pdfBuffer = await response.arrayBuffer();
  ```

  ```python example.py (Python) theme={null}
  response = requests.get(
      f"https://api.clickterm.com/public-client/v1/clickwrap-events/{event_id}/certificate",
      headers={
          "X-APP-ID": CLICKTERM_APP_ID,
          "X-APP-KEY": CLICKTERM_APP_KEY,
      },
  )
  with open("certificate.pdf", "wb") as f:
      f.write(response.content)
  ```
</CodeGroup>

Returns `application/pdf`.

## Clickwrap Agreement

The complete agreement PDF — includes the fully rendered clickwrap content (with all placeholders resolved) plus the Certificate of Acceptance appended at the end.

<Tip>
  This is the recommended document for record-keeping. It contains both the agreement
  content and the certificate in a single PDF.
</Tip>

### Endpoint

```
GET https://api.clickterm.com/public-client/v1/clickwrap-events/{clickwrapEventId}/agreement
```

| Parameter          | Required | Description                                                                                    |
| ------------------ | -------- | ---------------------------------------------------------------------------------------------- |
| `clickwrapEventId` | Yes      | The identifier for the Clickwrap Event from which you want to retrieve the Clickwrap Agreement |

<CodeGroup>
  ```java example.java (Java) theme={null}
  HttpResponse<InputStream> response = Unirest.get(
      "https://api.clickterm.com/public-client/v1/clickwrap-events/" + clickwrapEventId + "/agreement")
    .header("X-APP-ID", "YOUR_APP_ID")
    .header("X-APP-KEY", "YOUR_APP_KEY")
    .asBinary();
  Files.copy(response.getBody(), Path.of("agreement.pdf"));
  ```

  ```javascript example.js (Node.js) theme={null}
  const response = await fetch(
    `https://api.clickterm.com/public-client/v1/clickwrap-events/${eventId}/agreement`,
    {
      headers: {
        "X-APP-ID": process.env.CLICKTERM_APP_ID,
        "X-APP-KEY": process.env.CLICKTERM_APP_KEY,
      },
    }
  );
  const pdfBuffer = await response.arrayBuffer();
  ```

  ```python example.py (Python) theme={null}
  response = requests.get(
      f"https://api.clickterm.com/public-client/v1/clickwrap-events/{event_id}/agreement",
      headers={
          "X-APP-ID": CLICKTERM_APP_ID,
          "X-APP-KEY": CLICKTERM_APP_KEY,
      },
  )
  with open("agreement.pdf", "wb") as f:
      f.write(response.content)
  ```
</CodeGroup>

Returns `application/pdf`.

<Note>
  Both endpoints require a verified event with status `ACCEPTED`.
  Events with status `DECLINED`, `PENDING`, or `UNVERIFIED` will return an error.
</Note>

## Get clickwrap event details

Retrieve full metadata for a clickwrap event after it has been **verified**. Use it to audit the clickwrap lifecycle, cross-check template versions, or drive downstream workflows.

### Endpoint

```
GET https://api.clickterm.com/public-client/v1/clickwrap-events/{clickwrapEventId}/details
```

| Parameter          | Required | Description                                                |
| ------------------ | -------- | ---------------------------------------------------------- |
| `clickwrapEventId` | Yes      | The identifier for the Clickwrap Event you want to inspect |

<CodeGroup>
  ```java example.java (Java) theme={null}
  HttpResponse<String> response = Unirest.get(
      "https://api.clickterm.com/public-client/v1/clickwrap-events/" + clickwrapEventId + "/details")
    .header("X-APP-ID", "YOUR_APP_ID")
    .header("X-APP-KEY", "YOUR_APP_KEY")
    .asString();
  ```

  ```javascript example.js (Node.js) theme={null}
  const response = await fetch(
    `https://api.clickterm.com/public-client/v1/clickwrap-events/${eventId}/details`,
    {
      headers: {
        "X-APP-ID": process.env.CLICKTERM_APP_ID,
        "X-APP-KEY": process.env.CLICKTERM_APP_KEY,
      },
    }
  );
  const details = await response.json();
  ```

  ```python example.py (Python) theme={null}
  response = requests.get(
      f"https://api.clickterm.com/public-client/v1/clickwrap-events/{event_id}/details",
      headers={
          "X-APP-ID": CLICKTERM_APP_ID,
          "X-APP-KEY": CLICKTERM_APP_KEY,
      },
  )
  details = response.json()
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "clickwrapEventStatus": "ACCEPTED",
  "clickwrapEventId": "123e4567-e89b-12d3-a456-426614174000",
  "clickwrapTemplateId": "987e6543-e21b-45d3-b321-426614174999",
  "clickwrapTemplateVersion": 1,
  "clickwrapTemplateVersionMinor": 0,
  "endUserId": "423e4567-e89b-12d3-a456-426614174000",
  "templatePlaceholders": "{ \"email\": \"user@example.com\", \"phone\": \"+12345678900\" }",
  "technicalMetadata": "{\"userAgent\":\"okhttp/4.8.1\",\"ip\":\"a100:a100:a100:a100:a100:a100:a100:a100\"}",
  "presentedAt": "2025-08-20T14:25:00Z",
  "actionAt": "2025-08-20T14:30:00Z",
  "effectiveAt": "2025-08-20T14:00:00Z"
}
```

### Response fields

| Field                           | Type                      | Description                                                                 |
| ------------------------------- | ------------------------- | --------------------------------------------------------------------------- |
| `clickwrapEventStatus`          | String                    | `ACCEPTED` or `DECLINED`                                                    |
| `clickwrapEventId`              | UUID                      | Unique identifier for this Clickwrap Event                                  |
| `clickwrapTemplateId`           | UUID                      | The Clickwrap Template shown to the end user                                |
| `clickwrapTemplateVersion`      | Integer                   | Major version of the template used for this event                           |
| `clickwrapTemplateVersionMinor` | Integer                   | Minor version of the template used for this event                           |
| `endUserId`                     | String                    | The end user identifier linked to this event                                |
| `templatePlaceholders`          | String                    | JSON-encoded placeholder values used in the template (or null)              |
| `technicalMetadata`             | String                    | Metadata gathered from the end user's client (IP address, user agent, etc.) |
| `presentedAt`                   | Timestamp (UTC, ISO-8601) | When the clickwrap was presented to the end user                            |
| `actionAt`                      | Timestamp (UTC, ISO-8601) | When the user's action took place                                           |
| `effectiveAt`                   | Timestamp (UTC, ISO-8601) | When the template version became effective                                  |

## Show agreed content

Call `showAcceptedContent` to display the agreed content to an end user who has already accepted a clickwrap template. Make sure the SDK is initialized as shown in the [quickstart](/dev/quickstart-web).

<CodeGroup>
  ```java Android SDK theme={null}
  ClickwrapAcceptedAgreementRequest request = new ClickwrapAcceptedAgreementRequest(
      templateId, endUserId, "en"
  );

  ClicktermDialog.showAcceptedContent(this, request,
      new ClicktermDialog.OnAcceptedContentListener() {
          @Override
          public void onSuccess(ClickwrapTemplateContent content) {
              Log.i("Clickterm result: ", content.getContent());
              // The response will contain the agreed content
          }

          @Override
          public void onError(String message) {
              Log.e("Clickterm error: ", message);
          }
      }
  );
  ```

  ```javascript Web SDK theme={null}
  ClicktermDialog.showAcceptedContent({
      endUserId: options.endUser,
      clickwrapTemplateId: options.templateId,
  }).then((result) => {
      console.log('Clickwrap result:', result);
      // The response will contain the agreed content
  }).catch((error) => {
      console.error('Clickwrap error:', error);
  });
  ```
</CodeGroup>

| Parameter             | Required | Description                                            |
| --------------------- | -------- | ------------------------------------------------------ |
| `clickwrapTemplateId` | Yes      | The ID of your clickwrap template (from the dashboard) |
| `endUserId`           | Yes      | Your identifier for the end user (max 256 chars)       |

<Note>
  The end user will only be shown the agreed content dialog if they have accepted
  and the event has been verified.
</Note>

## Related

<CardGroup cols={2}>
  <Card title="Verifying a Signature" icon="shield-check" iconType="light" href="/dev/guides/verifying-signature">
    How to verify consent and create the event.
  </Card>

  <Card title="Checking consent status" icon="circle-check" iconType="light" href="/dev/guides/checking-consent-status">
    Query whether a user has accepted the latest version.
  </Card>

  <Card title="API reference — List events" icon="list" iconType="light" href="/api-reference/events/list-clickwrap-events">
    Reference for the clickwrap events listing endpoint.
  </Card>

  <Card title="API reference — Certificate" icon="square-terminal" iconType="light" href="/api-reference/events/download-certificate-of-acceptance">
    Full request/response details for the certificate endpoint.
  </Card>

  <Card title="API reference — Agreement" icon="square-terminal" iconType="light" href="/api-reference/events/download-signed-agreement">
    Full request/response details for the agreement endpoint.
  </Card>
</CardGroup>
