# App Review Process
Source: https://docs.orbitforms.ai/apps/app-review
Learn about the review process your app must go through before being listed in the OrbitForms marketplace.
Before your app can be listed in the OrbitForms marketplace, it must go through our review process. This ensures all apps meet our quality and security standards.
## Review Timeline
**3-5 Business Days** — Average review time for most applications.
Complex apps or those requiring additional security review may take longer. You'll receive email updates at each stage of the process.
## Review Stages
Complete your app profile, add screenshots, and ensure all required fields are filled.
Our team reviews your app configuration, permissions, and user experience.
We verify OAuth implementation, data handling, and security best practices.
If needed, we'll request changes. You can update and resubmit your app.
Once approved, your app will be listed in the OrbitForms marketplace.
## Submission Checklist
Ensure your app meets these requirements before submitting:
### Required
* App name and description
* Website URL
* Privacy policy URL
* Terms of service URL
* Valid OAuth callback URLs
### Optional
* App icon (image up to 5MB)
* Documentation link
## Common Rejection Reasons
Avoid these common issues that can lead to rejection:
* Missing or invalid privacy policy
* Requesting unnecessary permissions
* Insecure OAuth implementation
* Poor user experience or confusing flows
* Misleading app name or description
* Non-functional features or broken links
## After Approval
Your app will appear in the OrbitForms integrations directory.
Users can rate and review your app publicly.
Maintain quality standards to keep your listing active.
Minor updates go live instantly; major changes require re-review.
## Need help with your submission?
Our developer relations team is here to help you through the review process. Reach out if you have questions or need guidance.
Get help from our developer relations team.
# Authentication
Source: https://docs.orbitforms.ai/apps/authentication
Learn how to authenticate API requests using access tokens obtained through the OAuth 2.0 flow.
## Making Authenticated Requests
Include the access token in the Authorization header of your API requests:
```bash theme={null}
curl -X GET "https://orbitforms.ai/api/v1/forms" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json"
```
## Token Expiration
**Access tokens expire after 1 hour.** Use the refresh token to obtain a new access token without requiring the user to re-authorize.
To refresh an expired access token:
```bash theme={null}
curl -X POST "https://orbitforms.ai/api/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "refresh_token=YOUR_REFRESH_TOKEN"
```
## Authentication Errors
| Status | Error | Solution |
| ------ | -------------------- | ------------------------------------------------- |
| `401` | `invalid_token` | Token is expired or invalid. Refresh the token. |
| `401` | `token_expired` | Use your refresh token to get a new access token. |
| `403` | `insufficient_scope` | Request additional scopes from the user. |
| `429` | `rate_limited` | Too many requests. Implement exponential backoff. |
## Best Practices
Never expose tokens in client-side code or logs.
Refresh tokens before they expire to avoid interruptions.
Implement proper error handling for auth failures.
## Next Steps
Learn about available scopes
Make your first API call
# Best Practices
Source: https://docs.orbitforms.ai/apps/best-practices
Follow these best practices to build reliable, secure, and user-friendly integrations that scale with your users.
Follow these best practices to build reliable, secure, and user-friendly integrations that scale with your users.
## API Usage
Implement exponential backoff when you hit rate limits. Cache responses when possible to reduce API calls.
Use the page-based pagination (`page` and `per_page` parameters) for large result sets. Don't request more data than you need.
Store access tokens and refresh tokens securely. Never log tokens or expose them in client-side code.
## Webhook Handling
Return a 2xx response within 5 seconds. Queue processing for later if needed.
Store webhook IDs to handle duplicate deliveries gracefully.
Always validate webhook signatures before processing payloads.
Log failed processing and implement retry mechanisms.
## Error Handling
| Error Type | Recommended Action |
| ----------------------- | ------------------------------------------------------------- |
| `400 Bad Request` | Check your request parameters and payload format |
| `401 Unauthorized` | Refresh the access token and retry |
| `403 Forbidden` | Request additional scopes from the user |
| `404 Not Found` | Verify the resource ID exists |
| `429 Too Many Requests` | Implement exponential backoff |
| `500 Server Error` | Retry with exponential backoff, contact support if persistent |
## User Experience
* **Clear onboarding** — Guide users through setup with clear instructions and progress indicators.
* **Helpful error messages** — Show actionable error messages that help users resolve issues.
* **Sync status** — Show sync status and last successful sync time.
* **Easy disconnection** — Provide a clear way for users to disconnect your app.
## Next Steps
Review listing requirements.
Get your app approved.
# Developer Community
Source: https://docs.orbitforms.ai/apps/community
Connect with other developers building on OrbitForms. Get help, share ideas, and stay updated on the latest features.
Connect with other developers building on OrbitForms. Get help, share ideas, and stay updated on the latest features and best practices.
## Join the Conversation
Get help with API integration, report bugs, or ask questions about the platform.
Browse comprehensive guides, tutorials, and API reference documentation.
## Developer Resources
Complete API documentation.
Tips for building great apps.
# App Guidelines
Source: https://docs.orbitforms.ai/apps/guidelines
Guidelines to ensure apps in the OrbitForms marketplace provide a great experience for users.
These guidelines ensure apps in the OrbitForms marketplace provide a great experience for users. Following these requirements will help your app pass review quickly.
## Core Requirements
Implement OAuth 2.0 correctly, validate all inputs, and handle user data securely.
Provide clear UI, helpful error messages, and intuitive workflows.
Respond to webhooks within 5 seconds and maintain high availability.
Provide clear setup instructions and user documentation.
## Do's and Don'ts
### Do
* Request minimal permissions
* Provide clear error messages
* Include a privacy policy
* Handle rate limits gracefully
* Offer a way to disconnect
* Keep user data secure
### Don't
* Request unnecessary permissions
* Store tokens insecurely
* Ignore webhook failures
* Mislead users about functionality
* Collect data without consent
* Violate rate limits repeatedly
## Branding Requirements
| Item | Requirement |
| ----------- | ----------------------------------------------- |
| App Icon | 512x512 PNG, no transparency required |
| App Name | Clear, descriptive, no trademarks you don't own |
| Description | Accurate summary of features (max 500 chars) |
| Screenshots | At least 2 screenshots showing key features |
| Category | Select the most appropriate category |
## Privacy & Data Handling
Your app must respect user privacy and comply with data protection regulations:
* Publish a clear privacy policy explaining what data you collect and how it's used
* Only collect data necessary for your app's functionality
* Provide users a way to request data deletion
* Don't share user data with third parties without explicit consent
* Implement appropriate security measures to protect user data
## Next Steps
Submit for marketplace listing.
Tips for building great apps.
# App Marketplace
Source: https://docs.orbitforms.ai/apps/marketplace
Learn how to optimize your marketplace listing and grow your user base on the OrbitForms App Marketplace.
The OrbitForms App Marketplace is where users discover and install integrations. Learn how to optimize your listing and grow your user base.
## Marketplace Benefits
Access thousands of active OrbitForms users looking for integrations.
Verified apps get a trust badge and higher visibility.
Track installs, usage, and user engagement metrics.
One-click installation for users, seamless OAuth flow.
## Your Marketplace Listing
A great listing includes these elements:
* **App Icon** — A recognizable 512x512 icon that stands out in the directory.
* **App Name** — Clear, memorable name that describes your integration.
* **Short Description** — 140-character summary shown in search results.
* **Full Description** — Detailed explanation of features, use cases, and setup instructions.
* **Screenshots** — Visual demonstrations of your app in action (2-5 recommended).
* **Category** — Primary category for discovery (CRM, Automation, Analytics, etc.).
## Optimization Tips
1. Use keywords in your description that users search for
2. Include screenshots showing real use cases
3. Respond to user reviews promptly
4. Keep your app updated and bug-free
5. Provide excellent documentation
6. Offer responsive support
## App Categories
Apps can be listed under the following categories:
* Notifications
* CRM
* Automation
* Analytics
* Email Marketing
* Productivity
* Payments
* Database
* Developer Tools
## Next Steps
Review listing requirements.
Get your app approved.
# OAuth 2.0 Integration
Source: https://docs.orbitforms.ai/apps/oauth
OrbitForms uses OAuth 2.0 for secure authentication. This guide walks you through implementing the authorization code flow to access the OrbitForms API on behalf of users.
## OAuth Flow Overview
Redirect users to OrbitForms authorization page
User reviews and approves requested permissions
OrbitForms redirects back with an authorization code
Exchange the code for access and refresh tokens
Use the access token to make API requests
## Step 1: Build Authorization URL
Redirect users to the OrbitForms authorization endpoint with the following parameters:
```
https://orbitforms.ai/api/oauth/authorize?
client_id=YOUR_CLIENT_ID&
redirect_uri=https://yourapp.com/callback&
response_type=code&
scope=forms:read forms:write submissions:read&
state=RANDOM_STATE_STRING
```
| Parameter | Description |
| --------------- | --------------------------------------------- |
| `client_id` | Your application's Client ID |
| `redirect_uri` | Must match a registered callback URL |
| `response_type` | Always "code" for authorization code flow |
| `scope` | Space-separated list of requested permissions |
| `state` | Random string for CSRF protection |
## Step 2: Exchange Code for Tokens
After the user authorizes your app, they'll be redirected to your callback URL with an authorization code. Exchange this code for access and refresh tokens:
```bash theme={null}
curl -X POST https://orbitforms.ai/api/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "code=AUTHORIZATION_CODE" \
-d "redirect_uri=https://yourapp.com/callback"
```
**Response:**
```json theme={null}
{
"access_token": "YOUR_ACCESS_TOKEN",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "YOUR_REFRESH_TOKEN",
"scope": "forms:read forms:write submissions:read"
}
```
## Available Scopes
Request only the permissions your app needs:
Read form configurations
Create and update forms
Delete forms
Read form submissions
Update submission data
Delete submissions
Read contacts and tags
Create, update, and manage contacts and tags
Delete contacts
Read team information
Update team settings
Manage team members
Read webhook configurations
Create and manage webhooks
Read scheduling pages, event types, and availability
Create and update scheduling pages and event types
Delete scheduling pages and event types
Read meetings
Update meetings (status changes, notes)
Delete meetings
Read sequences, steps, enrollments, analytics, and unsubscribes
Enroll contacts and manage unsubscribes
Unenroll contacts and remove unsubscribes
Read form analytics
Read user profile
Update user profile
## Security Best Practices
Never expose your Client Secret in client-side code or version control.
Always include a random state string to prevent CSRF attacks.
Use refresh tokens to get new access tokens before they expire.
Only use pre-registered callback URLs to prevent open redirect vulnerabilities.
## Next Steps
Learn about permission scopes
Explore available endpoints
# Build Apps for OrbitForms
Source: https://docs.orbitforms.ai/apps/overview
Create powerful integrations and extend OrbitForms's functionality with custom OAuth applications. Connect your services, automate workflows, and reach thousands of users through the OrbitForms marketplace.
## Get Started
Register OAuth apps, manage API credentials, and access your developer tools.
Learn how to build OAuth applications that integrate with OrbitForms's API securely.
## Quick Start Guide
Follow these steps to create your first OrbitForms integration:
Create your account to get access to the developer tools.
Set up your app in the Developer Portal.
Define what your app can access and where users are redirected.
Integrate the authorization code flow into your application.
Get your app reviewed and listed in the marketplace.
## What You Can Build
Create powerful integrations that extend OrbitForms's capabilities:
Sync form submissions with your CRM
Trigger workflows from form events
Custom authentication integrations
Build tools for OrbitForms teams
## Resources
Complete API documentation with examples
Requirements for marketplace listing
Connect with other developers
**Ready to build?** Sign up and start building integrations today. Join hundreds of developers building on OrbitForms. [Get Started](/apps/portal)
# App Permissions
Source: https://docs.orbitforms.ai/apps/permissions
OAuth scopes define what your app can access on behalf of users. Request only the permissions your app needs—users are more likely to approve apps that request minimal access.
**Principle of Least Privilege** — Only request scopes that are essential for your app's core functionality. You can always request additional permissions later if needed.
## Forms
| Scope | Description |
| -------------- | ---------------------------------------------- |
| `forms:read` | Read form configurations, fields, and settings |
| `forms:write` | Create and update forms |
| `forms:delete` | Delete forms |
## Submissions
| Scope | Description |
| -------------------- | ----------------------------------- |
| `submissions:read` | Read form submissions and responses |
| `submissions:write` | Update submission data |
| `submissions:delete` | Delete form submissions |
## Contacts
| Scope | Description |
| ----------------- | -------------------------------------------- |
| `contacts:read` | Read contacts and tags |
| `contacts:write` | Create, update, and manage contacts and tags |
| `contacts:delete` | Delete contacts |
## Team
| Scope | Description |
| -------------- | --------------------- |
| `team:read` | Read team information |
| `team:write` | Update team settings |
| `team:members` | Manage team members |
## Webhooks
| Scope | Description |
| ---------------- | --------------------------------------- |
| `webhooks:read` | Read webhook configurations |
| `webhooks:write` | Create and manage webhook subscriptions |
## Scheduling
| Scope | Description |
| ------------------- | ---------------------------------------------------- |
| `scheduling:read` | Read scheduling pages, event types, and availability |
| `scheduling:write` | Create and update scheduling pages and event types |
| `scheduling:delete` | Delete scheduling pages and event types |
## Meetings
| Scope | Description |
| ----------------- | --------------------------------------- |
| `meetings:read` | Read meetings |
| `meetings:write` | Update meetings (status changes, notes) |
| `meetings:delete` | Delete meetings |
## Sequences
| Scope | Description |
| ------------------ | --------------------------------------------------------------- |
| `sequences:read` | Read sequences, steps, enrollments, analytics, and unsubscribes |
| `sequences:write` | Enroll contacts and manage unsubscribes |
| `sequences:delete` | Unenroll contacts and remove unsubscribes |
## Analytics
| Scope | Description |
| ---------------- | -------------------------------- |
| `analytics:read` | Read form analytics and insights |
## User
| Scope | Description |
| ------------ | ------------------- |
| `user:read` | Read user profile |
| `user:write` | Update user profile |
## Requesting Scopes
Include the scopes you need in the authorization URL as a space-separated list:
```
scope=forms:read submissions:read webhooks:read webhooks:write
```
## Common Scope Combinations
### Read-only Dashboard
View forms and submissions without making changes
`forms:read` `submissions:read`
### Form Builder
Create and manage form configurations
`forms:read` `forms:write`
### Full Integration
Complete access for building comprehensive integrations
`forms:read` `forms:write` `submissions:read` `webhooks:read` `webhooks:write`
## Next Steps
Implement the authorization flow
Submit for marketplace listing
# Developer Portal
Source: https://docs.orbitforms.ai/apps/portal
The Developer Portal is your central hub for creating and managing OAuth applications, accessing API credentials, and monitoring your integrations.
**Get started with the Developer Portal** — Sign up for an OrbitForms account to access the Developer Portal and start building integrations.
## Portal Features
Register new OAuth applications and configure their settings, redirect URIs, and permissions.
Generate and manage Client IDs and Client Secrets for your applications. Rotate credentials securely.
Track total installs of your app over time from the app detail page.
Update app settings, branding, descriptions, and callback URLs at any time.
Track the status of your app review submissions and receive feedback from our team.
## Creating Your First App
Once you have an OrbitForms account, follow these steps to register your first OAuth application:
From your dashboard, click "API & Developers" in the sidebar, then open the "OAuth Apps" tab to view your registered apps.
Start the app creation flow by clicking the "New App" button.
Fill in the required information:
* **App Name:** A unique name for your application
* **Description:** Brief explanation of what your app does
* **Website URL:** Your app's website
* **Redirect URIs:** OAuth callback URLs (can add multiple)
* **Scopes:** The permissions your app will request
After creation, you'll receive your Client ID and Client Secret. Store the secret securely—it won't be shown again.
## Next Steps
Implement the OAuth 2.0 flow
Get listed in the marketplace
# Webhooks
Source: https://docs.orbitforms.ai/apps/webhooks
Webhooks allow your app to receive real-time notifications when events occur in OrbitForms. Build reactive integrations that respond instantly to form submissions and other events.
## Available Events
New form submission received
Submission met qualification criteria
Submission data was modified
Submission was deleted
## Webhook Payload
Each webhook delivers a JSON payload with event details:
```json theme={null}
{
"event": "submission.created",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"form_id": "form_xyz789",
"form_title": "Contact Us",
"form_slug": "contact-us",
"submission_id": "sub_abc123",
"submission_data": {
"email": "user@example.com",
"name": "John Doe",
"message": "Hello!"
},
"submitted_at": "2024-01-15T10:29:58Z",
"metadata": {
"referrer": "https://example.com/contact",
"user_agent": "Mozilla/5.0 ...",
"device_type": "desktop",
"country": "US",
"utm_source": null,
"utm_medium": null,
"utm_campaign": null
}
}
}
```
## Signature Verification
All webhook requests include a signature header for verification. Always verify the signature to ensure the request came from OrbitForms:
```javascript theme={null}
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from('sha256=' + expectedSignature)
);
}
```
## Best Practices
Return a 2xx response within 5 seconds. Process asynchronously if needed.
Always validate the webhook signature before processing.
Webhooks are retried on failure. Implement idempotency to avoid duplicates.
## Next Steps
Full webhook documentation
Manage webhooks via API
# Changelog
Source: https://docs.orbitforms.ai/changelog
New features, improvements, and fixes in OrbitForms.
### New
* **"Added to another sequence" exit option** — Automatically remove a contact from a sequence when they're added to one or more sequences you choose. Perfect for handing contacts off from one campaign to the next. Find it in your sequence's **Settings → Exit criteria**.
* **HubSpot contact owner sync** — The HubSpot destination in workflows can now mirror the OrbitForms contact owner to the HubSpot contact owner, so the right rep owns the record in both tools. Enable it per workflow with the new **Sync contact owner** toggle.
* **AI credit alerts** — If your AI credits run out, we'll email you and show a warning on the Billing page so your AI-powered workflows never stop unexpectedly.
### Improvements
* **Smarter meeting gates** — Cancelled meetings no longer count toward a sequence's "Meeting booked" exit condition or the "Skip if meeting already booked" entry check, and skip reasons are now shown when a contact isn't enrolled.
* **Faster marketing site** — Public pages load noticeably faster.
* **Billing page refresh** — A cleaner, easier-to-scan billing summary with a quicker way to change plans.
* **Security hardening** — A round of platform-wide security improvements.
### Fixes
* Sequence analytics now correctly show delivered, open, click, and bounce metrics.
* Publishing a sequence no longer fails because of hidden leftover steps.
* Backspace and delete now remove variable pills in the token editor as expected.
* The contact page now shows friendly labels for every sequence exit reason.
# Authentication
Source: https://docs.orbitforms.ai/developers/api/authentication
The OrbitForms API uses API keys to authenticate requests. You can manage your API keys from your dashboard.
The OrbitForms API uses API keys to authenticate requests. You can manage your API keys from your dashboard.
## API Keys
There are two types of API keys:
`sk_live_*` — Live keys for production use. All requests affect real data.
`sk_test_*` — Test keys for development and testing, so you can distinguish non-production credentials in your dashboard.
## Using API Keys
Include your API key using either the `Authorization` header as a Bearer token, or the `X-API-Key` header:
```
Authorization: Bearer sk_live_your_api_key_here
# Or use the X-API-Key header:
X-API-Key: sk_live_your_api_key_here
```
Example request:
```bash theme={null}
curl -X GET "https://orbitforms.ai/api/v1/forms" \
-H "Authorization: Bearer sk_live_your_api_key_here" \
-H "Content-Type: application/json"
# Alternative with X-API-Key header:
curl -X GET "https://orbitforms.ai/api/v1/forms" \
-H "X-API-Key: sk_live_your_api_key_here" \
-H "Content-Type: application/json"
```
## OAuth 2.0
For third-party applications that need to access user data, use OAuth 2.0 with PKCE. OAuth access tokens use the `orb_at_*` prefix.
To build an OAuth app, visit the [Developer Portal](https://orbitforms.ai/developer) to register your application and obtain client credentials.
## Security Best Practices
**Keep keys secret** — Never expose API keys in client-side code, public repositories, or browser localStorage/sessionStorage.
**Use environment variables** — Store API keys in environment variables on your server. Never include them in frontend bundles.
**Rotate compromised keys** — If a key is exposed, revoke it immediately from your dashboard and generate a new one.
## Authentication Errors
| Status | Meaning |
| ------ | ---------------------------------- |
| `401` | Invalid or missing API key |
| `403` | API key lacks required permissions |
[Next: Forms API](/developers/api/forms)
# Forms API
Source: https://docs.orbitforms.ai/developers/api/forms
The Forms API allows you to create, read, update, and delete forms programmatically.
The Forms API allows you to create, read, update, and delete forms programmatically.
## Endpoints
| Method | Endpoint | Description |
| -------- | ---------------- | ------------------- |
| `GET` | `/v1/forms` | List all forms |
| `GET` | `/v1/forms/{id}` | Get a specific form |
| `POST` | `/v1/forms` | Create a new form |
| `PATCH` | `/v1/forms/{id}` | Update a form |
| `DELETE` | `/v1/forms/{id}` | Delete a form |
## Query Parameters
Use these query parameters when listing forms:
| Parameter | Type | Description |
| ---------- | ------- | ----------------------------------------------- |
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page (default: 20, max: 100) |
| `status` | string | Filter by status: published, draft, or archived |
## List Forms
Returns a paginated list of all forms in your team.
```json theme={null}
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Contact Form",
"slug": "contact-form",
"type": "standard",
"status": "published",
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-15T12:00:00Z"
}
],
"meta": {
"total": 1,
"page": 1,
"per_page": 20,
"total_pages": 1
}
}
```
## Get Form
Returns detailed information about a specific form, including fields and settings.
```json theme={null}
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Contact Form",
"slug": "contact-form",
"description": "Get in touch with our team",
"type": "standard",
"status": "published",
"fields": [
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"type": "email",
"label": "Email Address",
"name": "email",
"placeholder": "you@example.com",
"required": true,
"position": 0
},
{
"id": "660e8400-e29b-41d4-a716-446655440002",
"type": "textarea",
"label": "Message",
"name": "message",
"required": false,
"position": 1
}
],
"settings": {
"redirect_url": "https://example.com/thank-you"
},
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-15T12:00:00Z"
}
}
```
[Next: Submissions API](/developers/api/submissions)
# API Overview
Source: https://docs.orbitforms.ai/developers/api/overview
The OrbitForms REST API enables you to programmatically manage forms, submissions, scheduling pages, meetings, sequences, and integrate with your applications.
The OrbitForms REST API enables you to programmatically manage forms, submissions, scheduling pages, meetings, sequences, and integrate with your applications.
## Base URL
```
https://orbitforms.ai/api/v1
```
## Authentication
All API requests require authentication using a Bearer token in the Authorization header:
```
Authorization: Bearer YOUR_API_KEY
```
[Learn more about authentication](/developers/api/authentication)
## Available Endpoints
Create, read, update, and delete forms
Retrieve and manage form submissions
Manage scheduling pages, event types, meetings, and availability
Enroll contacts in drip campaigns, view analytics, manage unsubscribes
API keys and OAuth tokens
## Response Format
All responses are returned in JSON format with consistent structure:
```json theme={null}
{
"data": { ... },
"meta": {
"total": 100,
"page": 1,
"per_page": 20
}
}
```
# Rate Limits
Source: https://docs.orbitforms.ai/developers/api/rate-limits
The API enforces rate limits to ensure fair usage and platform stability.
## Rate Limits
| Authentication Type | Rate Limit |
| ------------------- | ---------------------- |
| API Key | 1,000 requests/minute |
| OAuth (Development) | 100 requests/minute |
| OAuth (Approved) | 10,000 requests/minute |
**Benefits of OAuth App Approval**
* **100x higher rate limits** – Scale without worrying about throttling
* **Marketplace listing** – Get discovered in the OrbitForms directory
* **Priority support** – Direct access to our developer relations team
[Learn about the review process →](https://orbitforms.ai/developer/app-review)
Need higher limits for your use case? Contact us at [support@orbitforms.ai](mailto:support@orbitforms.ai) to discuss custom rate limits for your application.
## Handling Rate Limits
**429 Too Many Requests**
When you exceed the rate limit, you'll receive a 429 response with a `Retry-After` header. Implement exponential backoff:
1. Wait for the time specified in the `Retry-After` header
2. Or implement exponential backoff (1s, 2s, 4s, 8s...)
3. Maximum retry time should be capped at 60 seconds
## Best Practices
* Cache responses when possible to reduce API calls
* Use webhooks instead of polling for real-time updates
* Batch operations when the API supports it
* Monitor your rate limit headers proactively
[Next: Webhooks →](/developers/webhooks)
# Scheduling API
Source: https://docs.orbitforms.ai/developers/api/scheduling
The Scheduling API lets you manage scheduling pages, event types, meetings, and availability schedules programmatically.
The Scheduling API lets you manage scheduling pages, event types, meetings, and availability schedules programmatically. Requires `scheduling:read`, `scheduling:write`, `meetings:read`, or `meetings:write` scopes.
## Scheduling Pages
Scheduling pages are booking pages your contacts use to schedule meetings. Each page can contain multiple event types.
### Endpoints
| Method | Endpoint | Description |
| -------- | --------------------------- | -------------------------------------- |
| `GET` | `/v1/scheduling-pages` | List scheduling pages |
| `POST` | `/v1/scheduling-pages` | Create a scheduling page |
| `GET` | `/v1/scheduling-pages/{id}` | Get a scheduling page with event types |
| `PATCH` | `/v1/scheduling-pages/{id}` | Update a scheduling page |
| `DELETE` | `/v1/scheduling-pages/{id}` | Delete a scheduling page |
### Query Parameters
Use these when listing scheduling pages:
| Parameter | Type | Description |
| ---------- | ------- | ---------------------------------------- |
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page (default: 20, max: 100) |
| `status` | string | Filter by status: draft or published |
### List Scheduling Pages
```bash theme={null}
curl https://orbitforms.ai/v1/scheduling-pages \
-H "Authorization: Bearer YOUR_API_KEY"
```
```json theme={null}
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Book a Demo",
"slug": "book-a-demo",
"description": "Schedule a product demo with our team",
"type": "schedule",
"page_type": "one_on_one",
"status": "published",
"settings": {
"confirmation_message": "You're booked!",
"show_avatar": true
},
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-20T14:30:00Z",
"published_at": "2026-01-16T09:00:00Z"
}
],
"meta": {
"total": 1,
"page": 1,
"per_page": 20,
"total_pages": 1
}
}
```
### Create a Scheduling Page
```bash theme={null}
curl -X POST https://orbitforms.ai/v1/scheduling-pages \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Book a Demo",
"slug": "book-a-demo",
"description": "Schedule a product demo",
"page_type": "one_on_one"
}'
```
### Get Scheduling Page
Returns the scheduling page with its event types included.
```json theme={null}
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Book a Demo",
"slug": "book-a-demo",
"description": "Schedule a product demo with our team",
"type": "schedule",
"page_type": "one_on_one",
"status": "published",
"settings": {
"confirmation_message": "You're booked!",
"show_avatar": true,
"redirect_url": "https://example.com/confirmed"
},
"remove_branding": false,
"event_types": [
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"title": "30 Min Meeting",
"slug": "30-min-meeting",
"duration_minutes": 30,
"location_type": "google_meet",
"is_active": true,
"color": "#3B82F6",
"position": 0,
"buffer_time_before": 0,
"buffer_time_after": 10,
"min_notice_minutes": 60,
"max_booking_days": 14,
"start_time_increment": 30,
"requires_confirmation": false,
"guests_allowed": true
}
],
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-20T14:30:00Z"
}
}
```
## Event Types
Event types define the different kinds of meetings available on a scheduling page (e.g., "30 Min Demo", "15 Min Quick Call"). Event type endpoints are nested under their parent scheduling page.
### Endpoints
| Method | Endpoint | Description |
| -------- | ----------------------------------------------------- | --------------------------- |
| `GET` | `/v1/scheduling-pages/{id}/event-types` | List event types for a page |
| `POST` | `/v1/scheduling-pages/{id}/event-types` | Create an event type |
| `GET` | `/v1/scheduling-pages/{id}/event-types/{eventTypeId}` | Get an event type |
| `PATCH` | `/v1/scheduling-pages/{id}/event-types/{eventTypeId}` | Update an event type |
| `DELETE` | `/v1/scheduling-pages/{id}/event-types/{eventTypeId}` | Delete an event type |
### Event Type Fields
| Field | Type | Description |
| ----------------------- | ------- | ------------------------------------------------------------------ |
| `title` | string | Display name (e.g., "30 Min Meeting") |
| `slug` | string | URL-friendly identifier (auto-generated from title if omitted) |
| `duration_minutes` | integer | Meeting duration in minutes (default: 30) |
| `location_type` | string | google\_meet, zoom, microsoft\_teams, phone, in\_person, or custom |
| `buffer_time_before` | integer | Minutes of buffer before the meeting (default: 0) |
| `buffer_time_after` | integer | Minutes of buffer after the meeting (default: 0) |
| `min_notice_minutes` | integer | Minimum advance notice required (default: 60) |
| `max_booking_days` | integer | How far in advance bookings are allowed (default: 14) |
| `start_time_increment` | integer | Time slot intervals: 5, 10, 15, 30, or 60 minutes |
| `requires_confirmation` | boolean | Whether the host must confirm the booking |
| `guests_allowed` | boolean | Whether attendees can add guests |
## Meetings
Meetings represent booked appointments. You can list, retrieve, update the status of, or delete meetings.
### Endpoints
| Method | Endpoint | Description |
| -------- | ------------------- | --------------------------------------------------------------------------- |
| `GET` | `/v1/meetings` | List meetings |
| `GET` | `/v1/meetings/{id}` | Get a meeting |
| `PATCH` | `/v1/meetings/{id}` | Update a meeting (status, notes). Cancelling cleans up Zoom and calendar. |
| `DELETE` | `/v1/meetings/{id}` | Delete a meeting. Cleans up the associated Zoom meeting and calendar event. |
### Query Parameters
Use these when listing meetings:
| Parameter | Type | Description |
| -------------------- | ------- | ------------------------------------------------------------------------------------- |
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page (default: 20, max: 100) |
| `status` | string | Filter: scheduled, completed, cancelled, pending\_confirmation, no\_show, rescheduled |
| `since` | string | ISO date. Only meetings starting after this time. |
| `until` | string | ISO date. Only meetings starting before this time. |
| `scheduling_page_id` | string | Filter by scheduling page UUID |
### List Meetings
```bash theme={null}
curl "https://orbitforms.ai/v1/meetings?status=scheduled&since=2026-02-01T00:00:00Z" \
-H "Authorization: Bearer YOUR_API_KEY"
```
```json theme={null}
{
"data": [
{
"id": "770e8400-e29b-41d4-a716-446655440010",
"attendee_name": "Jane Smith",
"attendee_email": "jane@example.com",
"start_time": "2026-02-10T14:00:00Z",
"end_time": "2026-02-10T14:30:00Z",
"timezone": "America/New_York",
"status": "scheduled",
"meeting_link": "https://meet.google.com/abc-defg-hij",
"notes": null,
"guests": [],
"contact_id": "880e8400-e29b-41d4-a716-446655440020",
"host_user_id": "990e8400-e29b-41d4-a716-446655440030",
"event_type_id": "660e8400-e29b-41d4-a716-446655440001",
"scheduling_page_id": "550e8400-e29b-41d4-a716-446655440000",
"created_at": "2026-02-08T09:15:00Z",
"updated_at": "2026-02-08T09:15:00Z"
}
],
"meta": {
"total": 1,
"page": 1,
"per_page": 20,
"total_pages": 1
}
}
```
### Update a Meeting
You can update the `status` (to *pending\_confirmation*, *scheduled*, *completed*, *cancelled*, *rescheduled*, or *no\_show*), `notes`, and `cancellation_reason` (when cancelling).
**Cancellation cleanup:** When you set the status to *cancelled*, OrbitForms automatically deletes the associated Zoom meeting (if one was created), removes the calendar event, and sends a cancellation notification email to the attendee.
```bash theme={null}
curl -X PATCH https://orbitforms.ai/v1/meetings/{id} \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "completed",
"notes": "Great demo call, follow-up scheduled"
}'
```
## Availability Schedules
Availability schedules define working hours and date-specific overrides (holidays, vacation, etc.) for team members. These endpoints are **read-only** via the public API since availability is tied to individual user calendars.
### Endpoints
| Method | Endpoint | Description |
| ------ | --------------------------------- | -------------------------------- |
| `GET` | `/v1/availability-schedules` | List availability schedules |
| `GET` | `/v1/availability-schedules/{id}` | Get schedule with date overrides |
### Query Parameters
| Parameter | Type | Description |
| --------- | ------ | ---------------------------------------- |
| `user_id` | string | Filter schedules by a specific user UUID |
### Get Availability Schedule
Returns the schedule with its weekly rules and any date-specific overrides.
```bash theme={null}
curl https://orbitforms.ai/v1/availability-schedules/{id} \
-H "Authorization: Bearer YOUR_API_KEY"
```
```json theme={null}
{
"data": {
"id": "aa0e8400-e29b-41d4-a716-446655440040",
"user_id": "990e8400-e29b-41d4-a716-446655440030",
"name": "Working Hours",
"timezone": "America/New_York",
"is_default": true,
"rules": [
{ "day": 1, "start": "09:00", "end": "17:00", "enabled": true },
{ "day": 2, "start": "09:00", "end": "17:00", "enabled": true },
{ "day": 3, "start": "09:00", "end": "17:00", "enabled": true },
{ "day": 4, "start": "09:00", "end": "17:00", "enabled": true },
{ "day": 5, "start": "09:00", "end": "17:00", "enabled": true }
],
"date_overrides": [
{
"id": "bb0e8400-e29b-41d4-a716-446655440050",
"date": "2026-02-17",
"is_unavailable": true,
"reason": "Holiday"
}
],
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-10T08:00:00Z"
}
}
```
## Calendar
These public-facing endpoints power the booking widget. They allow your contacts to check available time slots and book meetings without authentication. The availability endpoint accounts for the host's calendar events, buffer times, and date overrides. The booking endpoint creates the calendar event, generates the meeting link (Zoom or Google Meet), and sends a confirmation email to both parties. Microsoft Teams support coming soon.
These are public-facing endpoints used by the booking widget. They do not require an API key or authentication.
### Endpoints
| Method | Endpoint | Description |
| ------ | ---------------------------- | ------------------------------------ |
| `GET` | `/api/calendar/availability` | Get available time slots for booking |
| `POST` | `/api/calendar/book` | Book a meeting |
### Get Available Time Slots
Returns available time slots for a given host on a given date. Slots are calculated based on the host's availability schedule, existing calendar events, buffer times, and minimum notice requirements. Pass `event_type_id` (recommended) so the event type's duration, buffer, and booking-window rules apply; for round-robin and group pages, also pass `scheduling_page_id`.
#### Query Parameters
| Parameter | Type | Description |
| -------------------- | ------- | ------------------------------------------------------------------ |
| `user_id` | string | UUID of the host whose calendar to check (required) |
| `team_id` | string | UUID of the team that owns the scheduler (required) |
| `date` | string | Date to check, `YYYY-MM-DD` (required) |
| `duration` | integer | Meeting duration in minutes (default: event type setting, or 30) |
| `timezone` | string | IANA timezone, e.g. America/New\_York (default: UTC) |
| `event_type_id` | string | Event type UUID whose settings drive slot generation (recommended) |
| `scheduling_page_id` | string | Scheduling page UUID, for round-robin/group context (optional) |
```bash theme={null}
curl "https://orbitforms.ai/api/calendar/availability?user_id=990e8400-e29b-41d4-a716-446655440030&team_id=550e8400-e29b-41d4-a716-446655440000&date=2026-02-10&event_type_id=660e8400-e29b-41d4-a716-446655440001&timezone=America/New_York"
```
```json theme={null}
{
"date": "2026-02-10",
"duration": 30,
"timezone": "America/New_York",
"available_slots": [
{
"start": "2026-02-10T14:00:00.000Z",
"end": "2026-02-10T14:30:00.000Z"
},
{
"start": "2026-02-10T14:30:00.000Z",
"end": "2026-02-10T15:00:00.000Z"
}
]
}
```
Round-robin pages return an additional `round_robin: true` flag and an `available_host_count` on each slot.
### Book a Meeting
Books a meeting for the selected time slot. Creates a calendar event on the host's calendar, generates a meeting link (Zoom or Google Meet depending on the event type configuration; Microsoft Teams coming soon), and sends a confirmation email to both the host and attendee. Booking a slot that is already taken returns a `409` error.
#### Request Body
| Parameter | Type | Description |
| -------------------- | --------- | ------------------------------------------------------------------------ |
| `user_id` | string | UUID of the host to book with (required) |
| `team_id` | string | UUID of the team that owns the scheduler (required) |
| `start` | string | Meeting start time, ISO 8601 — from the availability response (required) |
| `end` | string | Meeting end time, ISO 8601 (required) |
| `attendee_email` | string | Attendee email address (required) |
| `attendee_name` | string | Attendee full name (optional; defaults to the email address) |
| `title` | string | Calendar event title (optional) |
| `description` | string | Calendar event description (optional) |
| `timezone` | string | IANA timezone of the attendee (optional) |
| `event_type_id` | string | Event type UUID being booked (optional, recommended) |
| `scheduling_page_id` | string | Scheduling page UUID (optional) |
| `guests` | string\[] | Array of additional guest email addresses (optional) |
| `notes` | string | Additional notes or message from the attendee (optional) |
| `lead_capture_data` | object | Lead capture field responses, e.g. phone number (optional) |
| `custom_fields` | object | Custom field values (optional) |
```bash theme={null}
curl -X POST https://orbitforms.ai/api/calendar/book \
-H "Content-Type: application/json" \
-d '{
"user_id": "990e8400-e29b-41d4-a716-446655440030",
"team_id": "550e8400-e29b-41d4-a716-446655440000",
"event_type_id": "660e8400-e29b-41d4-a716-446655440001",
"scheduling_page_id": "550e8400-e29b-41d4-a716-446655440000",
"start": "2026-02-10T14:00:00.000Z",
"end": "2026-02-10T14:30:00.000Z",
"timezone": "America/New_York",
"attendee_name": "Jane Smith",
"attendee_email": "jane@example.com",
"guests": ["colleague@example.com"],
"notes": "Interested in the enterprise plan"
}'
```
Returns `201 Created` with the meeting record, the calendar event, and the meeting link:
```json theme={null}
{
"success": true,
"meeting": {
"id": "770e8400-e29b-41d4-a716-446655440099",
"event_type_id": "660e8400-e29b-41d4-a716-446655440001",
"scheduling_page_id": "550e8400-e29b-41d4-a716-446655440000",
"host_user_id": "990e8400-e29b-41d4-a716-446655440030",
"contact_id": "880e8400-e29b-41d4-a716-446655440020",
"start_time": "2026-02-10T14:00:00.000Z",
"end_time": "2026-02-10T14:30:00.000Z",
"status": "scheduled",
"meeting_link": "https://meet.google.com/abc-defg-hij",
"timezone": "America/New_York",
"created_at": "2026-02-08T12:00:00Z"
},
"event": {
"id": "calendar-event-id",
"summary": "30 Min Meeting with Jane Smith",
"start": "2026-02-10T14:00:00.000Z",
"end": "2026-02-10T14:30:00.000Z",
"htmlLink": "https://calendar.google.com/event?eid=..."
},
"meeting_link": "https://meet.google.com/abc-defg-hij"
}
```
## Required Scopes
| Scope | Description |
| ------------------- | -------------------------------------------------------------- |
| `scheduling:read` | Read scheduling pages, event types, and availability schedules |
| `scheduling:write` | Create and update scheduling pages and event types |
| `scheduling:delete` | Delete scheduling pages and event types |
| `meetings:read` | Read meetings |
| `meetings:write` | Update meetings (status changes, notes) |
| `meetings:delete` | Delete meetings |
[Next: Rate Limits](/developers/api/rate-limits)
# Sequences API
Source: https://docs.orbitforms.ai/developers/api/sequences
Programmatically manage sequences (email and SMS steps), enroll contacts, and track engagement.
Sequences are created and edited in the dashboard. The API lets you list and inspect sequences and their steps, enroll and unenroll contacts, view analytics, and manage unsubscribes. Sequences with **SMS** steps require a valid **Send from number** and Salesmsg setup as described in the [Salesmsg integration](/integrations/salesmsg) guide.
## Available Endpoints
| Method | Endpoint | Description |
| -------- | ------------------------------------------------- | -------------------------- |
| `GET` | `/api/v1/sequences` | List all sequences |
| `GET` | `/api/v1/sequences/:id` | Get sequence details |
| `GET` | `/api/v1/sequences/:id/steps` | List a sequence's steps |
| `GET` | `/api/v1/sequences/:id/analytics` | Get sequence analytics |
| `GET` | `/api/v1/sequences/:id/enrollments` | List enrollments |
| `POST` | `/api/v1/sequences/:id/enrollments` | Enroll a contact |
| `DELETE` | `/api/v1/sequences/:id/enrollments/:enrollmentId` | Unenroll a contact |
| `GET` | `/api/v1/sequences/unsubscribes` | List unsubscribed contacts |
| `POST` | `/api/v1/sequences/unsubscribes` | Add unsubscribes |
**Authentication**
All Sequences API endpoints require a valid API key passed via the `Authorization: Bearer YOUR_API_KEY` header.
Get your API key from the [Developer Portal](https://orbitforms.ai/developer-portal).
Learn how sequences work
API rate limit details
# Submissions API
Source: https://docs.orbitforms.ai/developers/api/submissions
Retrieve and manage form submissions. Each submission contains the user's responses and metadata.
Retrieve and manage form submissions. Each submission contains the user's responses and metadata.
## Endpoints
| Method | Endpoint | Description |
| ------ | --------------------------------- | --------------------------- |
| `GET` | `/v1/forms/{form_id}/submissions` | List submissions for a form |
## Query Parameters
| Parameter | Type | Description |
| ---------- | ------- | -------------------------------------------- |
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page (default: 20, max: 100) |
| `since` | string | Filter submissions after this ISO 8601 date |
| `until` | string | Filter submissions before this ISO 8601 date |
| `status` | string | Filter by status: completed or partial |
## Example Response
`GET /v1/forms/{form_id}/submissions`
```json theme={null}
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"fields": {
"email": "user@example.com",
"message": "Hello, I have a question..."
},
"status": "completed",
"submitted_at": "2024-01-15T14:30:00Z",
"metadata": {
"referrer": "https://example.com",
"user_agent": "Mozilla/5.0...",
"device_type": "desktop",
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "spring_sale"
}
}
],
"meta": {
"total": 150,
"page": 1,
"per_page": 20,
"total_pages": 8
}
}
```
[Next: Scheduling API](/developers/api/scheduling)
# Best Practices
Source: https://docs.orbitforms.ai/developers/best-practices
Follow these recommendations to build reliable, secure, and performant integrations.
## Security
Use environment variables, never hardcode keys in source code.
Always validate the signature header before processing webhooks.
All webhook URLs must use HTTPS for secure communication.
Regenerate API keys regularly as a security best practice.
## Performance
Cache form configurations and reduce unnecessary API calls.
Request only the data you need with appropriate page sizes.
Use webhooks instead of polling for real-time updates.
Group related API calls when possible.
## Reliability
Implement proper error handling for all API responses.
Retry failed requests with increasing delays.
Handle duplicate webhook deliveries gracefully.
Track your API usage and stay within limits.
## Error Handling
| Code | Action |
| ----- | ------------------------------------------------- |
| `400` | Check request parameters |
| `401` | Verify API key is valid |
| `429` | Implement backoff and retry |
| `500` | Retry with backoff, contact support if persistent |
[Next: Troubleshooting →](/developers/troubleshooting)
# Core Concepts
Source: https://docs.orbitforms.ai/developers/core-concepts
Understand the fundamental concepts of the OrbitForms platform before diving into the API.
Understand the fundamental concepts of the OrbitForms platform before diving into the API.
## Forms
Forms are the primary resource in OrbitForms. Each form has a unique ID, contains fields, styling configuration, and settings for how submissions are handled.
* **Form ID:** Unique identifier (a UUID, e.g., `550e8400-e29b-41d4-a716-446655440000`)
* **Fields:** Input elements that collect data
* **Settings:** Configuration for notifications, redirects, etc.
* **Styling:** Visual appearance and branding
## Submissions
Submissions are the data collected when someone fills out a form. Each submission contains the field responses, metadata, and timestamps.
* **Submission ID:** Unique identifier for each response
* **Fields:** Key-value pairs of submitted data
* **Metadata:** Browser, IP, referrer, UTM parameters
* **Timestamps:** Created and updated times
## Teams
Forms belong to teams. Teams can have multiple members with different roles and permissions.
## API Keys
API keys authenticate your requests. Each key is scoped to a team and can have different permission levels.
## Webhooks
Webhooks send HTTP POST requests to your server when events occur, like new submissions or form updates.
## Next Steps
Explore the endpoints
Real-time events
# Embed Script
Source: https://docs.orbitforms.ai/developers/embed
Add OrbitForms forms to any website. Iframe for the most reliable inline embeds; the embed script for popup, slider, sidetab, and auto-resize.
## Iframe Embed
**Recommended for inline forms** — Pure HTML, no third-party script. Renders even when ad blockers, corporate firewalls, or strict CSPs would block scripts.
```html theme={null}
```
The small `
```
Or use the JavaScript API for more control:
```html theme={null}
```
## Popup Modal
Open the form in a modal overlay when a button is clicked. There are two approaches.
### Option 1: Native dialog + iframe (recommended)
Uses the native browser `
```html theme={null}
```
The native `