openapi: 3.0.3 info: title: Kajabi API V1 Authentication Forms API version: 1.1.0 description: "## Public API\n* Server URL `https://api.kajabi.com`\n* Endpoint paths are prefixed with `/v1`\n* Version endpoint `GET https://api.kajabi.com/v1/version`\n* See the [Developers Site](https://developers.kajabi.com) for documentation and examples.\n* Try the demo [Postman collection](https://www.postman.com/kajabi-apis/beta-public-api-demo/collection/fg4iyaz/kajabi-public-api-v1)\n## API Keys\n* Your API `client_id` and `client_secret` are available on the [User API Keys](https://app.kajabi.com/admin/settings/security) section of the Kajabi Admin Portal.\n * Custom API Keys can be created with specific permissions.\n * Click the \"Create User API Key\" button, enter a name (e.g. \"My project\"), select the user and permissions, and click \"Create\".\n * For security purposes, you may \"Delete\" or \"Rotate\" the api credentials at any time; which will invalidate any access tokens granted with the credentials.\n## Video Walkthroughs\n* [Capabilities](https://drive.google.com/file/d/1Puc9B2sSdA-RQb7YMxmUXg4FVoEXytoc/view?usp=sharing)\n* [Getting Started](https://drive.google.com/file/d/1hbGRShkxven_QMWvgYrerHKURbcZrnvJ/view?usp=sharing)\n* [Error Examples](https://drive.google.com/file/d/1i0wQK71I1jpaZVsxYwsn62gVj40S_E7Y/view?usp=sharing)\n* [External Contact Form](https://drive.google.com/file/d/1HqpULXvan5TOK3LvM7nILCuCkCaX0kFT/view?usp=sharing)\n" contact: email: support@kajabi.com name: Support url: https://help.kajabi.com/hc/en-us/articles/4404549690523-How-to-Get-Help-From-Kajabi-Live-Agents license: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0.html servers: - url: https://api.kajabi.com description: Production tags: - name: Forms paths: /v1/form_submissions: get: summary: List form submissions description: "Form submissions for authorized sites\n\n## Pagination\nUse `page[number]` and `page[size]` parameters to paginate results:\n### Get first page of 10 items\n* `GET /v1/form_submissions?page[number]=1&page[size]=10`\n### Get second page of 25 items\n* `GET /v1/form_submissions?page[number]=2&page[size]=25`\n\nThe response includes pagination links and meta data:\n```json\n{\n \"links\": {\n \"self\": \"https://api.kajabi.com/v1/form_submissions?page[number]=2&page[size]=10\",\n \"first\": \"https://api.kajabi.com/v1/form_submissions?page[number]=1&page[size]=10\",\n \"prev\": \"https://api.kajabi.com/v1/form_submissions?page[number]=1&page[size]=10\",\n \"next\": \"https://api.kajabi.com/v1/form_submissions?page[number]=3&page[size]=10\",\n \"last\": \"https://api.kajabi.com/v1/form_submissions?page[number]=5&page[size]=10\"\n },\n \"meta\": {\n \"total_pages\": 5,\n \"total_count\": 50,\n \"current_page\": 2\n }\n}\n```\n\n## Filtering\nUse filter parameters to narrow down results:\n### Filter by site ID\n* `GET /v1/form_submissions?filter[site_id]=123`\n### Filter by form ID\n* `GET /v1/form_submissions?filter[form_id]=456`\n\n## Sorting\nUse the `sort` parameter to sort results:\n### Sort by creation date (oldest first)\n* `GET /v1/form_submissions?sort=created_at`\n### Sort by name (alphabetical)\n* `GET /v1/form_submissions?sort=name`\n" tags: - Forms security: - Bearer: [] parameters: - name: sort in: query required: false description: 'Sort order, use: name, email, created_at. For descending order use ''-'' e.g. &sort=-name' schema: type: string - name: page[number] in: query required: false schema: type: integer - name: page[size] in: query required: false description: Number of documents schema: type: integer - name: filter[site_id] in: query required: false description: 'Filter by site ID, example: filter[site_id]=123' schema: type: string - name: filter[form_id] in: query required: false description: 'Filter by form ID, example: filter[form_id]=456' schema: type: string responses: '200': description: Success, filtered by form_id content: application/vnd.api+json: schema: $ref: '#/components/schemas/form_submissions_index_response' '401': description: Unauthorized, Authorization header is missing or invalid content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_unauthorized' '403': description: Forbidden, insufficient permission to access the resource content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_forbidden' /v1/form_submissions/{id}: get: summary: Form submission details description: 'Shows details of a form submission ## Form Submission Attributes * `name` (string) - The name of the person who submitted the form * `email` (string) - The email address of the person who submitted the form * `address_line_1` (string) - First line of address if provided * `address_line_2` (string) - Second line of address if provided * `address_city` (string) - City if provided * `address_country` (string) - Country if provided * `address_state` (string) - State if provided * `address_zip` (string) - ZIP/postal code if provided * `phone_number` (string) - Phone number if provided * `business_number` (string) - Business number if provided * `mobile_phone_number` (string) - Mobile phone number if provided ## Custom Fields Form submissions may also include custom field values that were collected through the form. ## Relationships Form submissions belong to: * A site * A form ## Include Related Resources Use the `include` parameter to load related resources: ### Include site and form * `GET /v1/form_submissions/123?include=site,form` ' tags: - Forms security: - Bearer: [] parameters: - name: id in: path required: true schema: type: string - name: include in: query required: false description: Load the related resources, for example ?include=site,form schema: type: string responses: '200': description: Success, shows details of a form submission content: application/vnd.api+json: schema: $ref: '#/components/schemas/form_submissions_show_response' '401': description: Unauthorized, Authorization header is missing or invalid content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_unauthorized' '403': description: Forbidden, insufficient permission to access the resource content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_forbidden' '404': description: Form submission not found content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_not_found' /v1/forms: get: summary: List forms description: "Contact forms for a site\n## Pagination\nUse `page[number]` and `page[size]` parameters to paginate results:\n### Get first page of 10 items\n* `GET /v1/forms?page[number]=1&page[size]=10`\n### Get second page of 25 items\n* `GET /v1/forms?page[number]=2&page[size]=25`\n\nThe response includes pagination links and meta data:\n```json\n{\n \"links\": {\n \"self\": \"https://api.kajabi.com/v1/forms?page[number]=2&page[size]=10\",\n \"first\": \"https://api.kajabi.com/v1/forms?page[number]=1&page[size]=10\",\n \"prev\": \"https://api.kajabi.com/v1/forms?page[number]=1&page[size]=10\",\n \"next\": \"https://api.kajabi.com/v1/forms?page[number]=3&page[size]=10\",\n \"last\": \"https://api.kajabi.com/v1/forms?page[number]=5&page[size]=10\"\n },\n \"meta\": {\n \"total_pages\": 5,\n \"total_count\": 50,\n \"current_page\": 2\n }\n}\n```\n## Sorting\nUse the `sort` parameter to sort the results:\n### Sort by title in ascending order\n* `GET /v1/forms?sort=title`\n### Sort by title in descending order\n* `GET /v1/forms?sort=-title`\n\nResponse will include forms sorted by the specified field\n```json\n{\n \"data\": [\n {\n \"id\": \"123\",\n \"type\": \"forms\",\n \"attributes\": {\n \"title\": \"Contact Form A\",\n \"description\": \"General contact form\"\n }\n },\n {\n \"id\": \"456\",\n \"type\": \"forms\",\n \"attributes\": {\n \"title\": \"Contact Form B\",\n \"description\": \"Newsletter signup form\"\n }\n }\n ]\n}\n```\n## Sparse Fields\nUse the `fields[forms]` parameter to request only specific attributes:\n### Only return title and description attributes\n* `GET /v1/forms?fields[forms]=title,description`\n\nResponse will only include requested fields\n```json\n{\n \"data\": [{\n \"id\": \"123\",\n \"type\": \"forms\",\n \"attributes\": {\n \"title\": \"Contact Form A\",\n \"description\": \"General contact form\"\n }\n }]\n}\n```\n## Filter by Site ID\nUse the `filter[site_id]` parameter to get forms for a specific site:\n### Get forms for site with ID 123\n* `GET /v1/forms?filter[site_id]=123`\n\nResponse will only include forms for that site\n```json\n{\n \"data\": [{\n \"id\": \"456\",\n \"type\": \"forms\",\n \"attributes\": {\n \"title\": \"Contact Form A\",\n \"description\": \"General contact form\"\n },\n \"relationships\": {\n \"site\": {\n \"data\": {\n \"id\": \"123\",\n \"type\": \"sites\"\n }\n }\n }\n }]\n}\n```\n## Filter by Title Contains\nUse the `filter[title_cont]` parameter to find forms where the title contains specific text:\n### Get forms with titles containing \"course\"\n* `GET /v1/forms?filter[title_cont]=course`\n\nResponse will include forms with matching titles\n```json\n{\n \"data\": [{\n \"id\": \"456\",\n \"type\": \"forms\",\n \"attributes\": {\n \"title\": \"Course Registration Form\",\n \"description\": \"Sign up form for online courses\"\n }\n }]\n}\n```\n## Using Multiple Parameters Together\nYou can combine pagination, sorting, sparse fields and filtering in a single request:\n### Get page 2 of forms for site 123, sorted by title descending, including only title and description fields\n* `GET /v1/forms?page[number]=2&page[size]=10&sort=-title&filter[site_id]=123&fields[forms]=title,description`\n\nResponse will include paginated and filtered forms with sparse fields\n```json\n{\n \"data\": [\n {\n \"id\": \"456\",\n \"type\": \"forms\",\n \"attributes\": {\n \"title\": \"Newsletter Form\",\n \"description\": \"Newsletter signup form\"\n },\n \"relationships\": {\n \"site\": {\n \"data\": {\n \"id\": \"123\",\n \"type\": \"sites\"\n }\n }\n }\n }\n ],\n \"links\": {\n \"self\": \"https://api.kajabi.com/v1/forms?page[number]=2&page[size]=10&sort=-title&filter[site_id]=123&fields[forms]=title,description\",\n \"first\": \"https://api.kajabi.com/v1/forms?page[number]=1&page[size]=10&sort=-title&filter[site_id]=123&fields[forms]=title,description\",\n \"prev\": \"https://api.kajabi.com/v1/forms?page[number]=1&page[size]=10&sort=-title&filter[site_id]=123&fields[forms]=title,description\",\n \"next\": null,\n \"last\": \"https://api.kajabi.com/v1/forms?page[number]=2&page[size]=10&sort=-title&filter[site_id]=123&fields[forms]=title,description\"\n },\n \"meta\": {\n \"total_pages\": 2,\n \"total_count\": 15,\n \"current_page\": 2\n }\n}\n```\n" tags: - Forms security: - Bearer: [] parameters: - name: sort in: query required: false description: 'Sort order, use: title for descending order use ''-'' e.g. &sort=-title' schema: type: string - name: page[number] in: query required: false schema: type: integer - name: page[size] in: query required: false description: Number of documents schema: type: integer - name: fields[forms] in: query required: false description: Partial attributes as specified, e.g. fields[forms]=title schema: type: string - name: filter[site_id] in: query required: false description: Filter by site_id, for example ?filter[site_id]=111 schema: type: string - name: filter[title_cont] in: query required: false description: Filter by title contains, for example ?filter[title_cont]=course schema: type: string responses: '200': description: Success, list of forms which the current user may access content: application/vnd.api+json: schema: $ref: '#/components/schemas/forms_index_response' '401': description: Unauthorized, Authorization header is missing or invalid content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_unauthorized' '403': description: Forbidden, insufficient permission to access the resource content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_forbidden' /v1/forms/{id}: get: summary: Form details description: "Shows details of a form\n\nForms belong to a site and can be associated with:\n* Landing pages\n* Offers\n* Email sequences\n* Events\n* Newsletters\n\n## Form Attributes\n* `title` (string) - A required field that represents the name or heading of the form. This is used to identify and display the form in the user interface. Forms must have a unique title within a site and can be searched and sorted by this attribute.\n* `default` (boolean) - A boolean flag indicating whether this is the default form for the site. Each site can have one default form, which is typically used when no specific form is specified. The default form can be accessed using the special ID \"default\" in API calls. When true, this form is considered the site's primary contact form.\n* `webhook_url` (string) - An optional URL where form submission data will be sent via webhook. This allows integration with external systems. The URL:\n * Must be a valid URL format\n * Cannot be a redirecting URL\n * Is automatically transformed and validated\n * Can be used to send form submission data to external services\n* `created_at` (string) - Timestamp indicating when the form was created. This is automatically set when the form is first created.\n* `updated_at` (string) - Timestamp indicating when the form was last modified. This is automatically updated whenever the form is changed.\n\n## Include Related Resources\nUse the `include` parameter to load related resources:\n### Include fields, offer, contact_tags\n* `GET /v1/forms/123?include=fields,offer,contact_tags`\n\nResponse will include the requested related resources\n```json\n{\n \"data\": {\n \"id\": \"123\",\n \"type\": \"forms\",\n \"attributes\": {\n \"title\": \"Contact Form\",\n \"default\": false,\n \"webhook_url\": null,\n \"created_at\": \"2025-02-27T01:03:09.179Z\",\n \"updated_at\": \"2025-02-27T01:03:25.365Z\"\n },\n \"relationships\": {\n \"fields\": {\n \"data\": [\n { \"id\": \"456\", \"type\": \"fields\" },\n { \"id\": \"789\", \"type\": \"fields\" }\n ]\n },\n \"offer\": {\n \"data\": { \"id\": \"123\", \"type\": \"offers\" }\n },\n \"contact_tags\": {\n \"data\": [\n { \"id\": \"456\", \"type\": \"contact_tags\" },\n { \"id\": \"789\", \"type\": \"contact_tags\" }\n ]\n }\n }\n },\n \"included\": [\n {\n \"id\": \"456\",\n \"type\": \"fields\", \"attributes\": { \"name\": \"Name\" }\n },\n {\n \"id\": \"789\",\n \"type\": \"fields\", \"attributes\": { \"name\": \"Email\" }\n },\n {\n \"id\": \"123\",\n \"type\": \"offers\", \"attributes\": { \"name\": \"Offer A\" }\n },\n {\n \"id\": \"456\",\n \"type\": \"contact_tags\", \"attributes\": { \"name\": \"Tag A\" }\n },\n {\n \"id\": \"789\",\n \"type\": \"contact_tags\", \"attributes\": { \"name\": \"Tag B\" }\n }\n ]\n}\n```\n### Field Attributes\nFields are used in:\n* Contact forms\n* Offer forms\n* Custom field sets\n* Form submissions\n\nThe system maintains default fields like `name`, `email`, etc. that cannot be removed\n\n* `title` (string) - The display name or label of the field. This is a required attribute that represents how the field will be shown to users in forms and interfaces. Aside from default fields, custom fields can have user-defined titles.\n* `type` (string) - The type of field, which must be one of these predefined types:\n * `TextField` - Standard text input\n * `PhoneField` - Phone number input\n * `EmailField` - Email address input\n * `TextAreaField` - Multi-line text input\n * `CheckboxField` - Boolean checkbox\n * `SelectBoxField` - Dropdown select\n * `RadioButtonsField` - Radio button group\n * `CountryField` - Country selector\n * `MobilePhoneField` - Mobile phone input\n* `required` (boolean) - A boolean indicating whether the field must be filled out. For default fields, this is set in the configuration, while custom fields can be marked as required or optional.\n* `handle` (string) - A unique identifier for the field within a site.\n * A custom handle in the format custom_N where N is a number from 1 to 150\n * The handle is used to reference the field in code and templates.\n* `select_options` (string) - For fields that have choices (`SelectBoxField`, `RadioButtonsField`), this contains the available options. The options are stored as newline-separated values and must be unique within the field.\n* `editable` (boolean) - A boolean indicating whether the field can be modified. Default fields typically have this set to false, while custom fields can be editable.\n* `created_at` (string) - Timestamp when the field was created.\n* `updated_at` (string) - Timestamp when the field was last updated.\n\n## Sparse Fields\nUse the `fields[forms]` parameter to request only specific attributes:\n### Only return title and webhook_url attributes\n* `GET /v1/forms/123?fields[forms]=title,webhook_url`\n\nResponse will only include requested fields\n```json\n{\n \"data\": [{\n \"id\": \"123\",\n \"type\": \"forms\",\n \"attributes\": {\n \"title\": \"Contact Form A\",\n \"webhook_url\": \"https://example.com/webhook\"\n }\n }]\n}\n```\n## Using Multiple Parameters Together\nYou can combine include and sparse fields in a single request:\n### Include fields (only name attribute) and only return title and webhook_url attributes\n* `GET /v1/forms/123?include=fields&fields[forms]=title,webhook_url&&fields[fields]=title`\n\nResponse will include related fields with sparse fields\n```json\n{\n \"data\": {\n \"id\": \"123\",\n \"type\": \"forms\",\n \"attributes\": {\n \"title\": \"Contact Form A\",\n \"webhook_url\": \"https://example.com/webhook\"\n },\n \"relationships\": {}\n },\n \"included\": [\n {\n \"id\": \"456\",\n \"type\": \"fields\",\n \"attributes\": {\n \"title\": \"Name\"\n }\n },\n {\n \"id\": \"789\",\n \"type\": \"fields\",\n \"attributes\": {\n \"title\": \"Email\"\n }\n }\n ]\n}\n```\n" tags: - Forms security: - Bearer: [] parameters: - name: id in: path required: true schema: type: string - name: include in: query required: false description: Load the related resources, for example ?include=fields,site,offer,contact_tags schema: type: string - name: fields[forms] in: query required: false description: Partial attributes as specified, e.g. fields[forms]=title,webhook_url schema: type: string responses: '200': description: Success, shows details of a form content: application/vnd.api+json: schema: $ref: '#/components/schemas/forms_show_response' '401': description: Unauthorized, Authorization header is missing or invalid content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_unauthorized' '403': description: Forbidden, insufficient permission to access the resource content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_forbidden' '404': description: form not found content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_not_found' /v1/forms/{id}/submit: post: summary: Submit form description: "## Submit a form\n* The `name` and `email` attributes are required.\n* The `email` attribute must be a valid and deliverable email address.\n\nExample request body:\n```json\n{\n \"data\": {\n \"type\": \"form_submissions\",\n \"attributes\": {\n \"name\": \"John Doe\",\n \"email\": \"john.doe@example.com\"\n }\n }\n}\n```\n\nResponse will include the newly created form submission resource.\n```json\n{\n \"data\": {\n \"id\": \"313\",\n \"type\": \"form_submissions\",\n \"attributes\": {\n \"name\": \"John Doe\",\n \"email\": \"john.doe@example.com\",\n \"address_line_1\": null,\n \"address_line_2\": null,\n \"address_city\": null,\n \"address_country\": null,\n \"address_state\": null,\n \"address_zip\": null,\n \"phone_number\": null,\n \"business_number\": null,\n \"mobile_phone_number\": null\n },\n \"relationships\": {\n \"site\": {\n \"data\": {\n \"id\": \"2\",\n \"type\": \"sites\"\n }\n },\n \"form\": {\n \"data\": {\n \"id\": \"15\",\n \"type\": \"forms\"\n }\n }\n }\n }\n}\n```\n## Behaviors and side effects\n* Checks for disposable emails\n* Validates email deliverability\n* Sends double opt-in email if needed\n* Subscribes contact (with opt-in handling)\n* Subscribes to SMS if applicable\n* Adds tags to contact\n* Grants offers if configured\n* Subscribes to email sequences\n* Delivers webhooks\n* Triggers automations\n" tags: - Forms security: - Bearer: [] parameters: - name: id in: path required: true schema: type: string responses: '201': description: Success, shows the form submission data content: application/vnd.api+json: schema: $ref: '#/components/schemas/form_submission_response' '401': description: Unauthorized, Authorization header is missing or invalid content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_unauthorized' '403': description: Forbidden, insufficient permission to access the resource content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors_forbidden' requestBody: content: application/vnd.api+json: schema: type: object properties: data: type: object properties: type: type: string attributes: $ref: '#/components/schemas/form_submission_attributes' required: - type - attributes required: - data components: schemas: form_attributes: type: object properties: title: type: - string - 'null' default: type: boolean webhook_url: type: object nullable: true url: type: string created_at: type: string format: date-time nullable: true readOnly: true description: ISO 8601 date-time, read only updated_at: type: string format: date-time nullable: true readOnly: true description: ISO 8601 date-time, read only form_submission_response: type: object properties: data: type: object properties: id: type: string type: type: string attributes: $ref: '#/components/schemas/form_submission_attributes' relationships: type: object properties: site: type: object properties: data: $ref: '#/components/schemas/resource_identifier' form: type: object properties: data: $ref: '#/components/schemas/resource_identifier' links: type: object properties: self: type: string current: type: string errors_not_found: type: object properties: errors: type: array items: $ref: '#/components/schemas/errors_attributes' resource_identifier: type: object properties: id: type: string type: type: string required: - id - type errors_attributes: type: object properties: status: type: string source: type: object nullable: true properties: pointer: type: string title: type: string detail: type: string form_submission_attributes: type: object properties: name: type: string email: type: string phone_number: type: - string - 'null' business_number: type: - string - 'null' address_line_1: type: - string - 'null' address_line_2: type: - string - 'null' address_city: type: - string - 'null' address_state: type: - string - 'null' address_country: type: - string - 'null' address_zip: type: - string - 'null' custom_1: type: string nullable: true description: Support depends on custom fields of a site custom_2: type: string nullable: true description: Support depends on custom fields of a site custom_3: type: string nullable: true description: Support depends on custom fields of a site forms_index_response: type: object properties: data: type: array items: type: object properties: id: type: string type: type: string enum: - forms attributes: $ref: '#/components/schemas/form_attributes' relationships: type: object properties: site: type: object properties: data: $ref: '#/components/schemas/resource_identifier' offer: type: object properties: data: $ref: '#/components/schemas/resource_identifier' fields: type: object properties: data: $ref: '#/components/schemas/resource_identifiers' forms_show_response: type: object properties: data: type: object properties: id: type: string type: type: string enum: - forms attributes: $ref: '#/components/schemas/form_attributes' relationships: type: object properties: site: type: object properties: data: $ref: '#/components/schemas/resource_identifier' offer: type: object properties: data: $ref: '#/components/schemas/resource_identifier' fields: type: object properties: data: $ref: '#/components/schemas/resource_identifiers' form_submissions_show_response: type: object properties: data: type: object properties: id: type: string type: type: string attributes: $ref: '#/components/schemas/form_submission_attributes' relationships: type: object properties: site: type: object properties: data: $ref: '#/components/schemas/resource_identifier' form: type: object properties: data: $ref: '#/components/schemas/resource_identifier' form_submissions_index_response: type: object properties: data: type: array items: type: object properties: id: type: string type: type: string attributes: $ref: '#/components/schemas/form_submission_attributes' relationships: type: object properties: site: type: object properties: data: $ref: '#/components/schemas/resource_identifier' form: type: object properties: data: $ref: '#/components/schemas/resource_identifier' links: type: object properties: self: type: string current: type: string resource_identifiers: type: array items: $ref: '#/components/schemas/resource_identifier' errors_unauthorized: type: object properties: errors: type: array items: $ref: '#/components/schemas/errors_attributes' errors_forbidden: type: object properties: errors: type: array items: $ref: '#/components/schemas/errors_attributes' securitySchemes: Bearer: type: http scheme: bearer x-mint: mcp: enabled: true