Forms¶
The Forms resource provides comprehensive methods to create, manage, and interact with forms and their submissions.
Initialization¶
List Forms¶
Retrieve a paginated list of forms.
Method¶
client.forms.all(
page: int = 1,
limit: int = 25,
workspace_id: str | None = None
) -> PaginatedForms
Parameters¶
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page |
int |
No | 1 |
Page number for pagination |
limit |
int |
No | 25 |
Items per page (max: 100) |
workspace_id |
str |
No | None |
Filter by workspace ID |
Returns¶
PaginatedForms object containing:
data: List ofFormobjectspage: Current page numbertotal_pages: Total number of pages
Example¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Get first page of forms
forms = client.forms.all(page=1, limit=10)
print(f"Page {forms.page} of {forms.total_pages}")
for form in forms.data:
print(f"Form: {form.name} (ID: {form.id})")
print(f" Status: {form.status}")
print(f" Submissions: {form.submission_count}")
Filtering by Workspace¶
# Get forms from a specific workspace
forms = client.forms.all(workspace_id="wksp_abc123")
for form in forms.data:
print(f"Form: {form.name}")
Iteration Support¶
The forms resource supports automatic pagination through iteration:
# Iterate through all forms automatically
for form in client.forms:
print(f"{form.name}: {form.submission_count} submissions")
Official Reference¶
Create Form¶
Create a new form with blocks and settings.
Method¶
client.forms.create(
name: str,
workspace_id: str,
blocks: list[dict] | None = None,
settings: dict | None = None
) -> FormCreated
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
str |
Yes | The form name |
workspace_id |
str |
Yes | The workspace ID where the form will be created |
blocks |
list[dict] |
No | List of form blocks (questions, text, images, etc.) |
settings |
dict |
No | Form settings configuration |
Returns¶
FormCreated object containing the created form's ID and edit URL.
Example: Simple Form¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Create a basic form
form = client.forms.create(
name="Customer Feedback",
workspace_id="wksp_abc123"
)
print(f"Form created: {form.id}")
print(f"Edit URL: {form.edit_url}")
Example: Form with Blocks¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Create a form with questions
form = client.forms.create(
name="Contact Form",
workspace_id="wksp_abc123",
blocks=[
{
"type": "INPUT_TEXT",
"payload": {
"text": [{"type": "p", "children": [{"text": "What's your name?"}]}],
"required": True
}
},
{
"type": "INPUT_EMAIL",
"payload": {
"text": [{"type": "p", "children": [{"text": "Your email address"}]}],
"required": True
}
},
{
"type": "TEXTAREA",
"payload": {
"text": [{"type": "p", "children": [{"text": "Your message"}]}],
"required": False
}
}
]
)
print(f"Form created with {len(form.blocks) if hasattr(form, 'blocks') else 0} blocks")
Example: Form with Settings¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Create form with custom settings
form = client.forms.create(
name="Survey 2024",
workspace_id="wksp_abc123",
settings={
"submitButtonText": "Send Response",
"showProgressBar": True,
"autoSave": True,
"respondOnce": True
}
)
print(f"Form created: {form.id}")
Official Reference¶
Get Form¶
Retrieve detailed information about a specific form.
Method¶
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
form_id |
str |
Yes | The form ID |
Returns¶
FormDetails object with complete form information including blocks and settings.
Example¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Get form details
form = client.forms.get(form_id="wXYz123")
print(f"Form: {form.name}")
print(f"Status: {form.status}")
print(f"Submissions: {form.submission_count}")
print(f"Created: {form.created_at}")
print(f"Blocks: {len(form.blocks)}")
# Access form blocks
for block in form.blocks:
print(f" Block type: {block.type}")
Official Reference¶
Update Form¶
Update a form's name, blocks, or settings.
Method¶
client.forms.update(
form_id: str,
name: str | None = None,
blocks: list[dict] | None = None,
settings: dict | None = None
) -> None
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
form_id |
str |
Yes | The form ID |
name |
str |
No | New form name |
blocks |
list[dict] |
No | Updated form blocks |
settings |
dict |
No | Updated form settings |
Returns¶
None (successful update returns no content)
Example: Update Name¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Update form name
client.forms.update(
form_id="wXYz123",
name="Customer Feedback 2024"
)
print("Form updated successfully")
Example: Update Settings¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Update form settings
client.forms.update(
form_id="wXYz123",
settings={
"respondOnce": True,
"showProgressBar": True,
"submitButtonText": "Submit Your Response"
}
)
print("Form settings updated")
Official Reference¶
Delete Form¶
Delete a form permanently.
Method¶
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
form_id |
str |
Yes | The form ID |
Returns¶
None (successful deletion returns no content)
Example¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Delete a form
client.forms.delete(form_id="wXYz123")
print("Form deleted successfully")
Permanent Deletion
Deleting a form is permanent and cannot be undone. All submissions will also be deleted.
Official Reference¶
List Form Questions¶
Retrieve all questions from a form.
Method¶
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
form_id |
str |
Yes | The form ID |
Returns¶
List of Question objects.
Example¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Get all questions from a form
questions = client.forms.list_questions(form_id="wXYz123")
for question in questions:
print(f"Question: {question.title}")
print(f" Type: {question.type}")
print(f" Required: {question.required}")
if question.fields:
for field in question.fields:
print(f" Field: {field.key} ({field.type})")
Official Reference¶
List Form Submissions¶
Retrieve submissions for a form with filtering and pagination.
Method¶
client.forms.list_submissions(
form_id: str,
filter: str = "all",
page: int = 1,
limit: int = 25,
since: str | None = None,
until: str | None = None
) -> PaginatedSubmissions
Parameters¶
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
form_id |
str |
Yes | - | The form ID |
filter |
str |
No | "all" |
Filter type: "all", "completed", "partial", "spam" |
page |
int |
No | 1 |
Page number |
limit |
int |
No | 25 |
Items per page (max: 100) |
since |
str |
No | None |
ISO 8601 date for start of range |
until |
str |
No | None |
ISO 8601 date for end of range |
Returns¶
PaginatedSubmissions object with submission data and counts.
Example¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Get all submissions
submissions = client.forms.list_submissions(
form_id="wXYz123",
filter="all",
page=1,
limit=50
)
print(f"Total submissions: {submissions.filter_count.all}")
print(f"Completed: {submissions.filter_count.completed}")
print(f"Partial: {submissions.filter_count.partial}")
for submission in submissions.data:
print(f"Submission: {submission.submission_id}")
print(f" Created: {submission.created_at}")
Example: Filter by Date Range¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Get submissions from last week
submissions = client.forms.list_submissions(
form_id="wXYz123",
filter="completed",
since="2024-01-01T00:00:00Z",
until="2024-01-07T23:59:59Z"
)
print(f"Submissions in date range: {len(submissions.data)}")
Official Reference¶
Get Form Submission¶
Retrieve a specific submission with all responses.
Method¶
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
form_id |
str |
Yes | The form ID |
submission_id |
str |
Yes | The submission ID |
Returns¶
SubmissionWithQuestions object containing submission data and questions.
Example¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Get specific submission
submission = client.forms.get_submission(
form_id="wXYz123",
submission_id="sub_abc456"
)
print(f"Submission ID: {submission.submission.submission_id}")
print(f"Created: {submission.submission.created_at}")
# Access responses
for response in submission.submission.responses:
question_key = response.key
answer = response.value
print(f"{question_key}: {answer}")
Official Reference¶
Delete Form Submission¶
Delete a specific submission from a form.
Method¶
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
form_id |
str |
Yes | The form ID |
submission_id |
str |
Yes | The submission ID to delete |
Returns¶
None (successful deletion returns no content)
Example¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Delete a submission
client.forms.delete_submission(
form_id="wXYz123",
submission_id="sub_abc456"
)
print("Submission deleted successfully")
Official Reference¶
Models¶
Form Model¶
Form
dataclass
¶
Represents a Tally form.
FormCreated Model¶
FormCreated
dataclass
¶
Response from creating a form.
FormDetails Model¶
FormDetails
dataclass
¶
Represents a complete Tally form with all blocks and settings.
This is returned by the get() method and includes the full form structure, unlike the simplified Form model used in list operations.
PaginatedForms Model¶
PaginatedForms
dataclass
¶
Represents a paginated response of forms.
Question Model¶
Question
dataclass
¶
Represents a question in a Tally form.
Submission Model¶
Submission
dataclass
¶
Represents a form submission.
SubmissionWithQuestions Model¶
SubmissionWithQuestions
dataclass
¶
Represents a submission response with its associated questions.
This is the response structure from the get_submission() endpoint, which includes both the submission details and all form questions.
PaginatedSubmissions Model¶
PaginatedSubmissions
dataclass
¶
Represents a paginated response of form submissions.
FormStatus Enum¶
FormStatus ¶
Bases: str, Enum
Form status types.
Values:
PUBLISHED: Form is live and accepting responsesDRAFT: Form is in draft modeCLOSED: Form is closed and not accepting responses
BlockType Enum¶
BlockType ¶
Bases: str, Enum
Form block types.
Common Block Types:
INPUT_TEXT: Single-line text inputINPUT_EMAIL: Email address inputINPUT_NUMBER: Number inputINPUT_PHONE_NUMBER: Phone number inputINPUT_LINK: URL inputINPUT_DATE: Date pickerTEXTAREA: Multi-line text inputCHECKBOX: Multiple choice (checkboxes)DROPDOWN: Dropdown selectLINEAR_SCALE: Linear scale ratingFILE_UPLOAD: File upload- And 60+ more block types...
Complete Example¶
from tally import Tally, NotFoundError
client = Tally(api_key="tly_your_api_key_here")
# Create a complete form
form = client.forms.create(
name="Product Feedback Survey",
workspace_id="wksp_abc123",
blocks=[
{
"type": "INPUT_TEXT",
"payload": {
"text": [{"type": "p", "children": [{"text": "What's your name?"}]}],
"required": True
}
},
{
"type": "INPUT_EMAIL",
"payload": {
"text": [{"type": "p", "children": [{"text": "Email address"}]}],
"required": True
}
},
{
"type": "LINEAR_SCALE",
"payload": {
"text": [{"type": "p", "children": [{"text": "Rate our product"}]}],
"min": 1,
"max": 10,
"required": True
}
},
{
"type": "TEXTAREA",
"payload": {
"text": [{"type": "p", "children": [{"text": "Additional feedback"}]}],
"required": False
}
}
],
settings={
"submitButtonText": "Send Feedback",
"showProgressBar": True,
"respondOnce": False
}
)
print(f"Form created: {form.id}")
print(f"Edit URL: {form.edit_url}")
# List all questions
questions = client.forms.list_questions(form_id=form.id)
print(f"\nForm has {len(questions)} questions")
# Get submissions
submissions = client.forms.list_submissions(
form_id=form.id,
filter="completed"
)
print(f"\nTotal submissions: {submissions.filter_count.completed}")
# Process each submission
for sub in submissions.data:
# Get full submission details
try:
full_sub = client.forms.get_submission(
form_id=form.id,
submission_id=sub.submission_id
)
print(f"\nSubmission: {full_sub.submission.submission_id}")
for response in full_sub.submission.responses:
print(f" {response.key}: {response.value}")
except NotFoundError:
print(f"Submission {sub.submission_id} not found")
Use Cases¶
Export Form Submissions¶
from tally import Tally
import json
client = Tally(api_key="tly_your_api_key_here")
# Export all submissions
submissions = client.forms.list_submissions(
form_id="wXYz123",
filter="completed",
limit=100
)
# Convert to JSON
export_data = []
for sub in submissions.data:
full_sub = client.forms.get_submission(
form_id="wXYz123",
submission_id=sub.submission_id
)
export_data.append({
"id": full_sub.submission.submission_id,
"created_at": full_sub.submission.created_at,
"responses": {r.key: r.value for r in full_sub.submission.responses}
})
with open("submissions.json", "w") as f:
json.dump(export_data, f, indent=2)
print(f"Exported {len(export_data)} submissions")
Clone a Form¶
from tally import Tally
client = Tally(api_key="tly_your_api_key_here")
# Get original form
original = client.forms.get(form_id="wXYz123")
# Create a copy
copy = client.forms.create(
name=f"{original.name} (Copy)",
workspace_id="wksp_abc123",
blocks=[block.to_dict() for block in original.blocks],
settings=original.settings.to_dict() if original.settings else None
)
print(f"Form cloned: {copy.id}")
Next Steps¶
- Webhooks - Set up real-time notifications for form submissions
- Workspaces - Organize forms into workspaces
- Error Handling - Handle form-related errors