Skip to main content

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.
This guide builds on the two-workflow pattern described in Create a Backend for Your Frontend. If you’re new to building web pages with backends in Pinkfish, start there first.

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]
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.
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

ComponentPurpose
HTML form pageHosted in file storage — reads customer ID from URL, loads/saves data
Customer responsesStored in a datastore collection, keyed by customer ID
Signed link with query paramsGenerated via filestorage skill (from Chat Mode or a Workflow) with query_params containing the customer ID