Skip to navigation

Responses API Walkthroughs

Common use cases and step-by-step guides for working with the Typeform Responses API

The Responses API lets you programmatically retrieve and manage responses submitted to your typeforms. You can fetch responses, filter by date or completion status, and implement compliance features like data deletion.

These walkthroughs assume you already have your Typeform access token and know how to pass it in the Authorization header of your request. If you need an access token, go to the Get Started section first.

Retrieve responses for a form

The most basic operation is retrieving all responses for a specific form.

Get all responses

GET https://api.typeform.com/forms/{form_id}/responses

This returns a paginated list of responses with:

  • Response IDs
  • Submission times
  • Calculated values (scores, etc.)
  • All question-answer pairs

Example response:

{
"total_items": 150,
"page_count": 15,
"items": [
{
"landing_id": "abc123xyz",
"token": "abc123xyz",
"response_id": "abc123xyz",
"landed_at": "2024-01-15T10:30:00Z",
"submitted_at": "2024-01-15T10:35:00Z",
"calculated": {
"score": 85
},
"answers": [
{
"field": {
"id": "field1",
"type": "short_text",
"ref": "name"
},
"type": "text",
"text": "John Smith"
}
]
}
]
}

Filter and paginate responses

Responses can be filtered by various criteria to get exactly what you need.

Filter by date range

Get responses submitted within a specific time period:

GET https://api.typeform.com/forms/{form_id}/responses?since=2024-01-01T00:00:00Z&until=2024-01-31T23:59:59Z

Parameters:

  • since: Include responses submitted after this datetime (ISO 8601 format)
  • until: Include responses submitted before this datetime (ISO 8601 format)

Filter by completion status

Get only completed responses:

GET https://api.typeform.com/forms/{form_id}/responses?completed=true

Or get partial/incomplete responses:

GET https://api.typeform.com/forms/{form_id}/responses?completed=false

Paginate through responses

Control pagination with page_size and before/after parameters:

# Get first page (25 responses)
GET https://api.typeform.com/forms/{form_id}/responses?page_size=25
# Get next page using the last response token
GET https://api.typeform.com/forms/{form_id}/responses?page_size=25&before={last_token}

The default page size is 25 responses. The maximum is 1000 per request.

Combine filters

You can combine multiple filters:

GET https://api.typeform.com/forms/{form_id}/responses?since=2024-01-01&completed=true&page_size=50

Retrieve specific responses

Get responses by ID

Fetch a specific response using its token:

GET https://api.typeform.com/forms/{form_id}/responses?included_response_tokens={token1},{token2},{token3}

This is useful when you need to check specific submissions or update records in your system.

Query specific fields

Retrieve only certain fields from responses:

GET https://api.typeform.com/forms/{form_id}/responses?fields={field_id1},{field_id2}

This reduces response payload size when you only need specific answers.

Sort responses

Order responses by submission time:

# Newest first (default)
GET https://api.typeform.com/forms/{form_id}/responses?sort=submitted_at,desc
# Oldest first
GET https://api.typeform.com/forms/{form_id}/responses?sort=submitted_at,asc

Handle file uploads

If your form includes file upload fields, response data includes download URLs:

{
"field": {
"id": "file_field",
"type": "file_upload",
"ref": "resume"
},
"type": "file_url",
"file_url": "https://api.typeform.com/forms/{form_id}/responses/{response_id}/fields/{field_id}/files/{filename}"
}

Download uploaded files

To download files from responses:

GET https://api.typeform.com/forms/{form_id}/responses/files

This returns a list of all uploaded files with download URLs.

Download a specific file

GET https://api.typeform.com/forms/{form_id}/responses/{response_id}/fields/{field_id}/files/{filename}

File URLs are temporary and expire after a period of time. Always download files promptly or store them in your own system if needed long-term.

Working with response data

Parse answers by type

Different field types return answers in different formats:

Text fields:

{
"type": "text",
"text": "User's answer"
}

Choice fields:

{
"type": "choice",
"choice": {
"id": "choice_id",
"label": "Selected option",
"ref": "option_a"
}
}

Multiple choices:

{
"type": "choices",
"choices": {
"ids": ["choice1_id", "choice2_id"],
"labels": ["Option A", "Option B"],
"refs": ["option_a", "option_b"]
}
}

Number fields:

{
"type": "number",
"number": 42
}

Date fields:

{
"type": "date",
"date": "2024-01-15"
}

Email fields:

{
"type": "email",
"email": "user@example.com"
}

URL fields:

{
"type": "url",
"url": "https://example.com"
}

Phone number fields:

{
"type": "phone_number",
"phone_number": "+1-555-0123"
}

Boolean fields:

{
"type": "boolean",
"boolean": true
}

Payment fields:

{
"type": "payment",
"payment": {
"amount": "99.99",
"currency": "USD",
"success": true,
"transaction_id": "ch_abc123"
}
}

Integration workflow

A typical integration workflow:

  1. Poll for new responses periodically:
GET https://api.typeform.com/forms/{form_id}/responses?since={last_check_time}
  1. Process each response in your application
  2. Store the submitted_at timestamp to use as since parameter for next poll
  3. Handle any file downloads needed
  4. Update your database with the response data

Example: Sync to database

// Pseudocode
async function syncResponses(formId, lastSyncTime) {
const url = `https://api.typeform.com/forms/${formId}/responses?since=${lastSyncTime}&completed=true`;
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
const data = await response.json();
for (const item of data.items) {
// Process and store each response
await saveToDatabase({
responseId: item.response_id,
submittedAt: item.submitted_at,
answers: item.answers,
score: item.calculated?.score,
});
}
// Update last sync time
if (data.items.length > 0) {
const latestTime = data.items[0].submitted_at;
await updateSyncTimestamp(latestTime);
}
}

Monitor response rates

Track form performance by analyzing response metadata:

// Calculate completion rate
const landedCount = responses.filter((r) => r.landed_at).length;
const completedCount = responses.filter((r) => r.submitted_at).length;
const completionRate = (completedCount / landedCount) * 100;
// Calculate average completion time
const completionTimes = responses
.filter((r) => r.landed_at && r.submitted_at)
.map((r) => new Date(r.submitted_at) - new Date(r.landed_at));
const avgTime =
completionTimes.reduce((a, b) => a + b, 0) / completionTimes.length;

Best practices

  1. Use pagination: Don’t try to fetch all responses at once for forms with many submissions
  2. Implement rate limiting: Respect API rate limits in your integration
  3. Cache responses: Store responses locally to reduce API calls
  4. Handle errors gracefully: Implement retry logic for failed requests
  5. Filter efficiently: Use date filters to only fetch new responses
  6. Process asynchronously: Handle response processing in background jobs
  7. Monitor API usage: Track your API usage to stay within limits

Error handling

Common scenarios to handle:

try {
const response = await fetchResponses(formId);
if (response.status === 404) {
// Form doesn't exist or you don't have access
}
if (response.status === 429) {
// Rate limit exceeded - wait and retry
}
if (response.status === 403) {
// Authorization issue - check your token
}
} catch (error) {
// Network or other errors
console.error('Failed to fetch responses:', error);
}

Next steps