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

# Tally as a data source

> Bring forms, submissions, and form analytics from Tally to Nekt.

Tally is an online form builder for creating forms, surveys, quizzes, and lead capture pages. The Tally connector extracts your workspaces, forms, questions, submissions with every answer, form analytics, and webhook delivery history.

## Configuring Tally as a Source

In the [Sources](https://app.nekt.ai/sources) tab, click on the "Add source" button located on the top right of your screen. Then, select the Tally option from the list of connectors.

Click **Next** and you'll be prompted to add your access.

### 1. Add account access

The connector authenticates with a Tally API key. To create one, open Tally and go to **Settings** > [**API keys**](https://tally.so/settings/api-keys), click **Create API key**, and copy the key. Tally shows the key only once.

<Note>
  An API key has the same access as the Tally user who created it. The connector extracts the workspaces and forms that user can see. If that user leaves your Tally organization, the key stops working.
</Note>

The following configurations are available:

* **API Key**: The Tally API key created above.
* **Start Date**: Only submissions submitted on or after this date are extracted on the first run. Leave it empty to extract all submissions.
* **Submission Status** (advanced, default `all`): Extract `all` submissions, only `completed` ones, or only `partial` ones.
* **Analytics Period** (advanced, default `30d`): The period requested from the form analytics streams. Options: `today`, `yesterday`, `24h`, `7d`, `30d`, `3m`, `6m`, `12m`, and `all`.

Once you're done, click **Next**.

### 2. Select streams

Choose which data streams you want to sync. For faster extractions, select only the streams that are relevant to your analysis.

> Tip: The stream can be found more easily by typing its name.

<Tip>
  Tally allows 100 API requests per minute. Each form uses about seven requests: one for its questions, one or more for its submissions, and five for analytics. If you don't need form analytics, deselect the five analytics streams to make extractions roughly three times faster on accounts with many forms.
</Tip>

Select the streams and click **Next**.

### 3. Configure data streams

Customize how you want your data to appear in your catalog. Select the desired layer where the data will be placed, a folder to organize it inside the layer, a name for each table (which will effectively contain the fetched data) and the type of sync.

* **Layer**: choose between the existing layers on your catalog. This is where you will find your new extracted tables as the extraction runs successfully.
* **Folder**: a folder can be created inside the selected layer to group all tables being created from this new data source.
* **Table name**: we suggest a name, but feel free to customize it. You have the option to add a **prefix** to all tables at once and make this process faster!
* **Sync Type**: you can choose between INCREMENTAL and FULL\_TABLE.
  * Incremental: every time the extraction happens, we'll get only the new data - which is good if, for example, you want to keep every record ever fetched.
  * Full table: every time the extraction happens, we'll get the current state of the data - which is good if, for example, you don't want to have deleted data in your catalog.

Once you are done configuring, click **Next**.

### 4. Configure data source

Describe your data source for easy identification within your organization, not exceeding 140 characters.

To define your [Trigger](https://docs.nekt.com/runs/scheduling-and-triggers), consider how often you want data to be extracted from this source. This decision usually depends on how frequently you need the new table data updated (every day, once a week, or only at specific times).

Optionally, you can define some additional settings:

* Configure Delta Log Retention and determine for how long we should store old states of this table as it gets updated. Read more about this resource [here](https://docs.nekt.com/get-started/core-concepts/resource-control).
* Determine when to execute an **Additional [Full Sync](https://docs.nekt.com/get-started/core-concepts/types-of-sync#additional-full-sync)**. This will complement the incremental data extractions, ensuring that your data is completely synchronized with your source every once in a while.

Once you are ready, click **Next** to finalize the setup.

### 5. Check your new source

You can view your new source on the [Sources](https://app.nekt.ai/sources) page. If needed, manually trigger the source extraction by clicking on the arrow button. Once executed, your data will appear in your Catalog.

<Warning>For you to be able to see it on your [Catalog](https://app.nekt.ai/catalog), you need at least one successful source run.</Warning>

# Streams and Fields

## Available streams

The table below lists every stream, its **slug** (the exact identifier to pass when creating the source via API), and a short description.

| Stream | Slug | Description |
| - | - | - |
| Current User | `current_user` | The Tally user who owns the API key. |
| Organization Users | `organization_users` | Members of the Tally organization. |
| Organization Invites | `organization_invites` | Pending invitations to the organization. |
| Workspaces | `workspaces` | Workspaces the user can access, with members, invites, and folders. |
| Folders | `folders` | Folders of each workspace (requires a Tally Pro plan). |
| Forms | `forms` | Forms with status, submission count, and payment settings. |
| Form Questions | `form_questions` | Questions of each form and their input fields. |
| Submissions | `submissions` | Form submissions, extracted incrementally by submission date. |
| Submission Responses | `submission_responses` | One row per answered question of each submission, extracted incrementally with its submission. |
| Form Analytics Metrics | `form_analytics_metrics` | Visits, submissions, starts, completions, and completion rate per form. |
| Form Visits Over Time | `form_visits_over_time` | Visit counts per form over time. |
| Form Submissions Over Time | `form_submissions_over_time` | Completed and partial submission counts per form over time. |
| Form Visitor Dimensions | `form_visitor_dimensions` | Visitors per form by source, browser, OS, device, country, and city. |
| Form Drop-off | `form_drop_off` | Per-question views, answers, and drop-off rates. |
| Webhooks | `webhooks` | Webhooks configured on your forms (secrets are not extracted). |
| Webhook Events | `webhook_events` | Delivery attempts of each webhook, with status and payload. |

<Note>
  Streams that Tally restricts by plan or role (such as folders, organization users and invites, and form analytics) are skipped with a warning in the run log when the API key's user does not have access to them. The rest of the extraction continues normally.
</Note>

## Fields by stream

Fields holding nested objects or lists of objects (for example `payments`, `members`, `fields`, `responses`, and `payload`) are stored as JSON strings. In `submission_responses`, `answer` is always JSON-encoded, so text answers appear in quotes and multiple-choice answers appear as lists.

<AccordionGroup>
  <Accordion title="Current User">
    The Tally user who owns the API key.

    Primary key: `id`

    * `id` - Unique identifier of the user
    * `first_name` - First name of the user
    * `last_name` - Last name of the user
    * `full_name` - Full name of the user
    * `email` - Email address of the user
    * `avatar_url` - URL of the user's avatar image
    * `organization_id` - Identifier of the organization the user belongs to
    * `is_deleted` - Whether the user account was deleted
    * `has_two_factor_enabled` - Whether the user has two-factor authentication enabled
    * `subscription_plan` - Subscription plan of the user (FREE, PRO or BUSINESS)
    * `created_at` - When the user was created
    * `updated_at` - When the user was last updated
  </Accordion>

  <Accordion title="Organization Users">
    Users that are members of the organization.

    Primary key: `id`

    * `id` - Unique identifier of the user
    * `first_name` - First name of the user
    * `last_name` - Last name of the user
    * `full_name` - Full name of the user
    * `email` - Email address of the user
    * `avatar_url` - URL of the user's avatar image
    * `organization_id` - Identifier of the organization the user belongs to
    * `is_deleted` - Whether the user account was deleted
    * `has_two_factor_enabled` - Whether the user has two-factor authentication enabled
    * `subscription_plan` - Subscription plan of the user (FREE, PRO or BUSINESS)
    * `created_at` - When the user was created
    * `updated_at` - When the user was last updated
  </Accordion>

  <Accordion title="Organization Invites">
    Pending invitations to join the organization.

    Primary key: `id`

    * `id` - Unique identifier of the invite
    * `organization_id` - Identifier of the organization the invite is for
    * `email` - Email address that was invited
    * `created_at` - When the invite was created
    * `updated_at` - When the invite was last updated
  </Accordion>

  <Accordion title="Workspaces">
    Workspaces the API key's user has access to.

    Primary key: `id`

    * `id` - Unique identifier of the workspace
    * `name` - Name of the workspace
    * `index` - Display position of the workspace in the Tally dashboard
    * `members` - Users with access to the workspace (JSON array of user objects)
    * `invites` - Pending invites to the workspace (JSON array of objects with id, email and workspaceIds)
    * `folders` - Folders in the workspace (JSON array of folder objects)
    * `created_by_user_id` - Identifier of the user who created the workspace
    * `created_at` - When the workspace was created
    * `updated_at` - When the workspace was last updated
  </Accordion>

  <Accordion title="Folders">
    Folders of each workspace (folders require a Tally Pro subscription).

    Primary key: `id`

    * `id` - Unique identifier of the folder
    * `name` - Name of the folder
    * `workspace_id` - Identifier of the workspace that contains the folder
    * `parent_id` - Identifier of the parent folder, empty for top-level folders
    * `created_by_user_id` - Identifier of the user who created the folder
    * `created_at` - When the folder was created
    * `updated_at` - When the folder was last updated
  </Accordion>

  <Accordion title="Forms">
    Forms the API key's user has access to.

    Primary key: `id`

    * `id` - Unique identifier of the form
    * `name` - Name of the form
    * `is_name_modified_by_user` - Whether the form name was set by the user rather than derived from the title
    * `workspace_id` - Identifier of the workspace that contains the form
    * `organization_id` - Identifier of the organization that owns the form
    * `status` - Publication status of the form: BLANK, DRAFT or PUBLISHED
    * `has_draft_blocks` - Whether the form has unpublished changes
    * `number_of_submissions` - Total number of submissions received by the form
    * `is_closed` - Whether the form is closed to new submissions
    * `index` - Display position of the form in its workspace
    * `payments` - Payment amounts and currencies configured in the form (JSON array of objects)
    * `created_at` - When the form was created
    * `updated_at` - When the form was last updated
  </Accordion>

  <Accordion title="Form Questions">
    Questions of each form.

    Primary key: `form_id`, `id`

    * `id` - Unique identifier of the question
    * `form_id` - Identifier of the form the question belongs to
    * `type` - Block type of the question (e.g. INPUT\_TEXT, MULTIPLE\_CHOICE, CHECKBOXES)
    * `title` - Title of the question as shown to respondents
    * `is_title_modified_by_user` - Whether the title was set by the user rather than generated
    * `is_deleted` - Whether the question was removed from the form
    * `number_of_responses` - Number of responses the question received
    * `fields` - Input fields of the question with uuid, type, questionType and title (JSON array of objects)
    * `created_at` - When the question was created
    * `updated_at` - When the question was last updated
  </Accordion>

  <Accordion title="Submissions">
    Submissions of each form, read incrementally by submission date.

    Primary key: `id`. Incremental on `submitted_at`.

    * `id` - Unique identifier of the submission
    * `form_id` - Identifier of the form that was submitted
    * `respondent_id` - Identifier of the respondent who submitted the form
    * `is_completed` - Whether the submission is complete (false for partial submissions)
    * `submitted_at` - When the submission was submitted, used as the incremental replication key
    * `preview_url` - Signed URL to view the submission in a browser (contains an access token, no expiry)
    * `pdf_url` - Signed URL to download the submission as a PDF (contains an access token, no expiry)
    * `response_count` - Number of questions answered in the submission
    * `responses` - Answers of the submission (JSON array of answer objects); one row per answer in submission\_responses
  </Accordion>

  <Accordion title="Submission Responses">
    One row per answered question of each submission.

    Primary key: `id`

    * `id` - Unique identifier of the response
    * `submission_id` - Identifier of the submission the response belongs to
    * `form_id` - Identifier of the form
    * `question_id` - Identifier of the question that was answered
    * `question_title` - Title of the question at extraction time
    * `question_type` - Block type of the question at extraction time
    * `respondent_id` - Identifier of the respondent
    * `session_uuid` - Identifier of the respondent's session
    * `answer` - Answer value as JSON; its shape depends on the question type (text, number, list of options, file objects, ...)
    * `formatted_answer` - Answer formatted as text by Tally (e.g. numbers with custom formatting)
    * `created_at` - When the response was created
    * `updated_at` - When the response was last updated
    * `submitted_at` - When the submission was submitted, used as the incremental replication key
  </Accordion>

  <Accordion title="Form Analytics Metrics">
    Aggregate metrics of each form for the configured period.

    Primary key: `form_id`, `period`

    * `form_id` - Identifier of the form
    * `period` - Analytics period requested from Tally (e.g. 30d, 12m, all), from the analytics\_period setting
    * `visits` - Number of visits to the form
    * `visit_duration` - Average visit duration
    * `submissions` - Number of submissions
    * `unique_respondents` - Number of unique respondents
    * `total_views` - Total number of form views
    * `starts` - Number of respondents who started the form
    * `completions` - Number of respondents who completed the form
    * `completion_duration` - Average time to complete the form
    * `completion_rate` - Share of starts that were completed
  </Accordion>

  <Accordion title="Form Visits Over Time">
    Visit counts of each form over time.

    Primary key: `form_id`, `period`, `bucket`

    * `form_id` - Identifier of the form
    * `period` - Analytics period requested from Tally (e.g. 30d, 12m, all), from the analytics\_period setting
    * `bucket` - Time bucket key exactly as returned by Tally
    * `bucket_start` - Start of the time bucket, parsed from the bucket key when possible
    * `interval` - Length of each time bucket as reported by Tally
    * `total_visits` - Number of visits in the bucket
  </Accordion>

  <Accordion title="Form Submissions Over Time">
    Completed and partial submission counts of each form over time.

    Primary key: `form_id`, `period`, `bucket`

    * `form_id` - Identifier of the form
    * `period` - Analytics period requested from Tally (e.g. 30d, 12m, all), from the analytics\_period setting
    * `bucket` - Time bucket key exactly as returned by Tally
    * `bucket_start` - Start of the time bucket, parsed from the bucket key when possible
    * `interval` - Length of each time bucket as reported by Tally
    * `completed` - Number of completed submissions in the bucket
    * `partial` - Number of partial submissions in the bucket
  </Accordion>

  <Accordion title="Form Visitor Dimensions">
    Visitor counts of each form broken down by source, browser, OS, device, country and city.

    Primary key: `form_id`, `period`, `dimension`, `value`

    * `form_id` - Identifier of the form
    * `period` - Analytics period requested from Tally (e.g. 30d, 12m, all), from the analytics\_period setting
    * `dimension` - Breakdown dimension: source, browser, os, device, country or city
    * `value` - Value of the dimension (e.g. a browser name or a country)
    * `visitors` - Number of visitors with this value
  </Accordion>

  <Accordion title="Form Drop-off">
    Per-question drop-off statistics of each form.

    Primary key: `form_id`, `period`, `block_group_uuid`

    * `form_id` - Identifier of the form
    * `period` - Analytics period requested from Tally (e.g. 30d, 12m, all), from the analytics\_period setting
    * `block_group_uuid` - Identifier of the question block group
    * `title` - Title of the question
    * `type` - Block type of the question
    * `is_required` - Whether the question is required
    * `views` - Number of times the question was viewed
    * `started_views` - Number of views by respondents who had started the form
    * `answers` - Number of answers to the question
    * `drops` - Number of respondents who left the form at this question
    * `answer_rate` - Share of views that resulted in an answer
    * `drop_rate` - Share of views that resulted in leaving the form
  </Accordion>

  <Accordion title="Webhooks">
    Webhooks configured on the forms the user has access to.

    Primary key: `id`

    * `id` - Unique identifier of the webhook
    * `form_id` - Identifier of the form the webhook is attached to
    * `url` - Endpoint URL the webhook delivers to
    * `http_header_names` - Names of the custom HTTP headers sent with each delivery (JSON array; values are not extracted)
    * `event_types` - Event types the webhook subscribes to (e.g. FORM\_RESPONSE)
    * `external_subscriber` - Identifier of the external integration that created the webhook, if any
    * `is_enabled` - Whether the webhook is enabled
    * `last_synced_at` - When the webhook was last synced
    * `created_at` - When the webhook was created
    * `updated_at` - When the webhook was last updated
  </Accordion>

  <Accordion title="Webhook Events">
    Delivery attempts of each webhook, with status, response code and payload.

    Primary key: `id`

    * `id` - Unique identifier of the webhook event
    * `webhook_id` - Identifier of the webhook that produced the event
    * `webhook_url` - URL the event was sent to
    * `event_type` - Type of event (FORM\_RESPONSE)
    * `delivery_status` - Delivery status: QUEUED, SUCCEEDED, FAILED or DROPPED
    * `status_code` - HTTP status code returned by the receiving endpoint
    * `response` - Response body returned by the receiving endpoint
    * `retry` - Number of delivery retry attempts
    * `payload` - Payload that was sent to the endpoint (JSON object)
    * `created_at` - When the event was created
    * `updated_at` - When the event was last updated
  </Accordion>
</AccordionGroup>

## Implementation Notes

* **Submissions** are extracted incrementally using `submitted_at`. Each run reads submissions submitted on or after the last extracted one, so the newest submission can appear again in the next run.
* **Analytics** streams are snapshots of the configured **Analytics Period**. Each row carries the `period` it was requested for.
* **Signed links**: `preview_url` and `pdf_url` in `submissions` are links generated by Tally that never expire. Anyone with the link can see the submission, so share these columns carefully.
* **Rate limit**: Tally allows 100 API requests per minute per API key. The connector stays under this limit and waits automatically when Tally asks it to slow down. Other integrations using the same key share this limit.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.