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

# Personalized Web Forms with Signed Links

> Create web forms that remember each customer's progress using unique IDs in signed URLs

## Why use this?

When you host an HTML form in Pinkfish file storage, you can generate personalized signed links for each customer that include a unique ID as a query parameter. The form reads that ID from the URL and uses it to save and retrieve the customer's responses from a datastore. This means customers can fill out a form over multiple sessions — their progress is saved and pre-populated when they return.

<Note>
  This guide builds on the two-workflow pattern described in [Create a Backend for Your Frontend](/how-to/create-a-backend-for-your-frontend). If you're new to building web pages with backends in Pinkfish, start there first.
</Note>

## Example Use Cases

* **Customer intake forms** — Send each customer a personalized link. They can fill out the form at their own pace, and their answers are saved automatically when they return.

* **Application forms** — Generate a unique link per applicant so they can save progress and come back to complete their submission.

* **Surveys with follow-up** — Send personalized survey links where responses are tied to a specific customer record for follow-up actions.

## How It Works

1. You create an HTML form page and save it in a file storage collection
2. When you want to share the form with a customer, you generate a signed link that includes a unique customer ID (e.g. `?customerId=JohnSmith-90210`)
3. You email that link to the customer
4. When the customer opens the link, the HTML page reads the customer ID from the URL
5. The page checks the datastore for an existing entry with that ID — if found, it pre-populates the form
6. When the customer submits, the page saves their responses to the datastore using that ID as the key
7. If the customer returns later using the same link, their previous answers are already filled in

## Prerequisites

* A **file storage collection** to host the HTML form
* A **datastore collection** to store customer responses

## Step 1: Create the HTML Form

Build your HTML page with a prompt like this:

```
Build an HTML form page that will be hosted in Pinkfish file storage. The page must:

1. On load, read the "customerId" from the URL query string using:
   new URLSearchParams(window.location.search).get('customerId')

2. If a customerId is present, call the datastore to look up an existing
   record with that key

3. If a record exists, pre-populate all form fields with the saved data

4. When the user submits the form, save (or update) a datastore record
   using the customerId as the key

5. Show a success message after saving

Use the datastore skill with collectionId: [YOUR_DATASTORE_COLLECTION_ID]

Save the HTML file to file storage collection: [YOUR_FILESTORAGE_COLLECTION_ID]
with the filename: customer-form.html

The form fields are: [list your fields, e.g. First Name, Last Name, Email,
Phone, Address, Notes]
```

<Tip>
  Replace `[YOUR_DATASTORE_COLLECTION_ID]` and `[YOUR_FILESTORAGE_COLLECTION_ID]` with your actual collection IDs. You can find these in your Pinkfish dashboard under Data Collections.
</Tip>

## Step 2: Generate Signed Links with Customer IDs

You can generate personalized signed links from either an **agent** or a **workflow step**. Both use the same filestorage skill.

### Option A: Generate from an Agent

Enter a prompt like this:

```
Get me a signed link for the file "customer-form.html" in my file storage
collection [YOUR_FILESTORAGE_COLLECTION_ID].

Set the link to expire in 7 days, and include a query parameter called
"customerId" with the value "JohnSmith-90210".
```

The agent will return a signed URL with the customer ID embedded in it.

### Option B: Generate from a Workflow

In a workflow step, use the filestorage skill to get a signed URL:

```
Get a signed URL for "customer-form.html" in collection [YOUR_FILESTORAGE_COLLECTION_ID]
with file_links_expire_in_days set to 7 and query_params set to
{"customerId": "JohnSmith-90210"}
```

### Option C: Add to Your Agent's System Prompt

If you want your agent to generate links on demand without repeating the full instructions each time, add this to your agent's system prompt:

```
When I ask you to generate a form link for a customer:

1. Create a unique customer ID by combining their name and zip code
   (e.g. "JohnSmith-90210") — no spaces, use hyphens

2. Use the filestorage skill to get a signed URL for the file
   "customer-form.html" in collection [YOUR_FILESTORAGE_COLLECTION_ID]:
   - Set file_links_expire_in_days to 7
   - Set query_params to {"customerId": "<the-unique-id>"}

3. Return the signed URL so I can email it to the customer
```

Then you can simply say:

> "Generate a form link for John Smith, zip 90210"

### The Result

The agent or workflow will return a signed URL like:

```
.../files/{collectionId}/customer-form.html?signed-key=xxx&customerId=JohnSmith-90210
```

Email this link to your customer. They can open it, fill out the form, and come back later to continue where they left off.

## What the Customer Experiences

1. They receive an email with a personalized link
2. They click the link and see the form — empty on first visit, pre-filled on return visits
3. They fill out fields and click Submit — their responses are saved
4. If they return later using the same link, everything they entered before is already there

## Summary

| Component                     | Purpose                                                                                                       |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------- |
| HTML form page                | Hosted in **file storage** — reads customer ID from URL, loads/saves data                                     |
| Customer responses            | Stored in a **datastore** collection, keyed by customer ID                                                    |
| Signed link with query params | Generated via filestorage skill (from Chat Mode or a Workflow) with `query_params` containing the customer ID |
