---
title: Retool
description: Concise Retool pattern for uploading Plainterms documents and
  receiving rendered PDF webhooks.
editUrl: true
head: []
tableOfContents:
  minHeadingLevel: 2
  maxHeadingLevel: 3
template: doc
sidebar:
  order: 10
  label: Retool
  hidden: false
  attrs: {}
pagefind: true
draft: false
---

This is the current Plainterms pattern for one Retool app plus one Retool
Workflow. It uses Retool's REST API resource and webhook trigger terminology,
and only the Plainterms API/webhook contracts that exist today.

## Shape

Create one Retool REST API resource for Plainterms:

- Base URL: your Plainterms app origin.
- Authentication: Bearer token using the Plainterms organization API key.
- Global header: `Authorization: Bearer <Plainterms API key>`.

The API key identifies the organization, not a user. The upload query passes
`user_email` so Plainterms can set document ownership, dashboard visibility,
and webhook `uploaded_by` attribution. Pass `customer_document_id` when Retool
or your CRM has a stable quote/document ID, and reuse that same value whenever
the user retries or re-uploads the same logical document.

## Upload Query

![Retool upload sequence](/diagrams/retool-upload-flow.svg)

1. The Retool user selects a Plainterms user email and a PDF.
2. A Retool REST query sends JSON metadata to `POST /api/v1/documents`.
3. Include optional `customer_document_id` from the Retool row, CRM quote, or
   policy document record when you want stable downstream correlation. Do not
   generate a fresh value inside the upload button handler for each click.
4. Plainterms returns `202` with a `reservation` object describing what
   happened. Dispatch on `reservation.next_action`: `"upload"` means the response
   includes a signed storage `PUT` URL; `"none"` means the content is already
   satisfied server-side -- skip the upload and poll the returned document
   instead (see
   [Handling Duplicate Uploads](/public-api/#handling-duplicate-uploads)).
5. When an `upload` object is present, Retool uploads the PDF bytes to that
   signed URL with `content-type: application/pdf`.

Retool REST queries support JSON bodies for the reservation call and raw or
binary bodies for the signed upload. Retool file components expose `.value`;
adapt that value to the binary upload query your Retool app uses.

## Stable Customer Document IDs

Treat `customer_document_id` as the Retool or customer-system key for the
logical quote/document, not the upload attempt. Store it on the source row or
derive it deterministically from the source record before calling
`POST /api/v1/documents`.

Good Retool patterns:

- Use the CRM quote ID already shown in the selected table row.
- Use a policy-system document ID returned by the upstream system.
- Derive a deterministic content key from a customer record and document slot
  that your app owns.

Avoid values created with `uuid()` or `Date.now()` inside the upload action.
Those values rotate on retry. If the same PDF is re-uploaded with a new
`customer_document_id`, Plainterms may return a `409` identity conflict instead
of treating the request as a duplicate or retry for the existing logical
document.

## Polling And Downloads

After upload, poll one of:

- `GET /api/v1/documents/{documentId}`
- `GET /api/v1/documents/custId-{customerDocumentId}`

The metadata response includes `document.polling` and `document.download`.
When `document.download.available` is `true`, fetch `document.download.url`
with the same Plainterms API key. The URL is an absolute URL to
`/api/v1/documents/{documentId}.pdf`; it is not an anonymous signed link.

## Workflow Webhook Trigger

![Retool webhook sequence](/diagrams/retool-webhook-flow.svg)

1. Plainterms sends an outbound webhook to the Retool Workflow webhook URL.
2. Retool exposes the request as `startTrigger.headers`,
   `startTrigger.pathParams`, and `startTrigger.data`.
3. If `startTrigger.data.download_url` is present, use the same Plainterms REST
   resource/API key to `GET` that URL.
4. Store or display the rendered PDF for the Retool user record that maps to
   `uploaded_by.email` and `customer_document_id`.

Retool recommends an `X-Workflow-Api-Key` for authenticating workflow webhook
triggers. That protects the Retool URL; it is separate from Plainterms'
`Webhook-Signature`. If your integration requires Plainterms HMAC verification,
verify `Webhook-Signature: t=<timestamp>,v1=<hmac>` over
`<timestamp>.<raw JSON body>` in code before trusting the payload.

## Correlation

- `document_id` is the Plainterms document UUID.
- `customer_document_id` is the caller's stable quote/document key from upload.
  Reuse the same value when the same quote/document is uploaded again.
- `uploaded_by.id` and `uploaded_by.email` identify the Plainterms user matched
  from upload `user_email`.
- The same `customer_document_id` can be used later with
  `/api/v1/documents/custId-{customerDocumentId}` and
  `POST /api/v1/documents/confirm`.

## Current Boundaries

- There is no public webhook configuration endpoint today.
- There is no public API-key management endpoint today.
- There is no public document listing/search endpoint today.
- There is no multipart Plainterms upload endpoint. When an upload is
  required (`reservation.next_action: "upload"`), it uses the signed storage
  `PUT` URL returned by `POST /api/v1/documents`.
- Do not send `uploaded_by` in the document request. Use `user_email`.
- Webhook `download_url` values require the same Plainterms API key and do not
  include `download_url_expires_at`.

For exact request/response shapes, see [Public API](/public-api/). For webhook
payload fields and signature verification, see [Webhooks](/webhooks/).