Windsor.ai Connectors API Documentation
Overview
Windsor.ai Connectors provide a unified API to access data from over 300 marketing, analytics, and business platforms. This documentation will guide you through the process of using our API to retrieve data from various sources.
Getting started
Authentication
All API requests require an API key for authentication. You can obtain your API key from your Windsor.ai account.
Include your API key in all requests using the api_key parameter:
https://connectors.windsor.ai/{connector}?api_key=your_api_key_here&fields=date,spend
Alternatively, you can pass your API key in a request header instead of the query string. This is useful when your client injects secrets into request headers rather than the URL (for example, agent platforms such as Anthropic’s Claude). Send it either as an X-Api-Key header:
X-Api-Key: your_api_key_here
or as a bearer token in the Authorization header:
Authorization: Bearer your_api_key_here
All three methods are equivalent and return the same data. If you supply the key both as a query parameter and as a header, the query parameter takes precedence.
Base URL
The base URL for all API requests is:
https://connectors.windsor.ai
Making API requests
Basic request structure
A basic API request follows this format:
https://connectors.windsor.ai/{connector}?fields={field1,field2,...}&api_key={your_api_key}
Where:
{connector}is the name of the data source (e.g., facebook, googleanalytics4, linkedin){field1,field2,...}is a comma-separated list of fields you want to retrieve{your_api_key}is your Windsor.ai API key
Required parameters
Every API request must include these parameters:
| Parameter | Description |
|---|---|
api_key |
Your Windsor.ai API key |
fields |
Comma-separated list of fields to retrieve |
Optional parameters
You can customize your data request with these optional parameters:
| Parameter | Description | Example |
| date_preset | Predefined date range | last_7d, last_30d, last_90d, last_year |
| date_from | Start date (YYYY-MM-DD) | 2023-01-01 |
| date_to | End date (YYYY-MM-DD) | 2023-01-31 |
| _max_rows | Maximum number of records to return | 100 |
| filter | Filter expression | [[“campaign”,”eq”,”search_competitors_tier1″]] |
Public (sub)hourly refreshes via API
You can control how often recent data is refreshed from the upstream platform by using two parameters:refresh_since and refresh_interval.
This behaves the same way as our scheduled destination tasks (in databases and warehouse destinations), but is exposed publicly via the Connectors API.
All requests using these parameters remain subject to the global API rate limits.
How these parameters work:
1) refresh_since
- Default: 3d (currently, it supports only the last 3 days).
- Defines the recent time window that will be retrieved again from the upstream API.
- Data within this period is re-fetched according to
refresh_interval. - Data older than this period is considered stable and will be served from the cache if available.
- The global cache refresh interval doesn’t apply to this stable data.
2) refresh_interval
- Default: 6h.
- Defines how often data in the
refresh_sincewindow should be refreshed from the upstream API. - The system will request new data from the source at most once every
refresh_interval. - This setting doesn’t affect the stable cache outside the
refresh_sincewindow.
Notes:
The minimum allowed refresh_interval depends on your plan:
STANDARDandPLUSplans can userefresh_interval=1hor more (e.g.1h,2h,6h, …).;PROFESSIONALandENTERPRISEtiers can userefresh_interval=15minor more (e.g.15min,30min,1h, …).
Example:
To refresh the last 3 days of Google Ads data at least once per hour:
https://connectors.windsor.ai/google_ads?api_key=API_KEY&fields=date,campaign,spend&refresh_since=3d&refresh_interval=1h
Code examples
Python
import requests
API_KEY = "your_api_key_here"
connector = "facebook"
fields = "date,campaign,spend,impressions,clicks"
url = f"https://connectors.windsor.ai/{connector}?api_key={API_KEY}&fields={fields}"
response = requests.get(url)
print(response.json())
Javascript
const API_KEY = "your_api_key_here";
const connector = "facebook";
const fields = "date,campaign,spend,impressions,clicks";
const url = `https://connectors.windsor.ai/${connector}?api_key=${API_KEY}&fields=${fields}`;
fetch(url)
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error("API error:", err));
Write actions
Some connectors expose write actions: operations that change something on the source platform (for example create or pause a campaign, set a budget, or boost a post) rather than only reading data. The same endpoint is used to discover the available actions and to execute them. It powers the write capabilities exposed to Claude and other LLMs through the Windsor.ai MCP, and can be called directly from your own software.
Write actions must be enabled for your team before they can be executed. Enable them under Team management. Available actions differ per connector, so always call the list endpoint (GET) first rather than assuming an action exists.
List actions
GET https://connectors.windsor.ai/{connector}/actions
Returns the write operations the connector supports, each with a JSONSchema describing its parameters. Authenticate with api_key or access_token as a query parameter.
Example request:
curl "https://connectors.windsor.ai/google_ads/actions?api_key=YOUR_API_KEY"
Example response:
[
{
"id": "create_campaign",
"name": "Create campaign",
"description": "Create a new campaign (created paused).",
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"budget_amount_micros": { "type": "integer" },
"channel_type": { "type": "string" },
"bidding_strategy": { "type": "string" }
},
"required": ["name", "budget_amount_micros"]
}
}
]
Execute an action
POST https://connectors.windsor.ai/{connector}/actions
Runs one action against one connected account. Requires write actions to be enabled for the team. Send a JSON body with these fields:
| Field | Required | Description |
|---|---|---|
| account | Yes | The connected account id to run the action against. |
| action | Yes | The action id from the list endpoint (for example create_campaign). |
| params | No | Object of action parameters, matching the action JSONSchema. |
Example request:
curl -X POST "https://connectors.windsor.ai/google_ads/actions?api_key=YOUR_API_KEY" -H "Content-Type: application/json" -d '{"account":"1234567890","action":"create_campaign","params":{"name":"Summer Sale","budget_amount_micros":50000000,"channel_type":"SEARCH","bidding_strategy":"manual_cpc"}}'
Example success response:
{ "result": "Campaign 'Summer Sale' created successfully with status PAUSED." }
Error responses: 400 for a missing field or invalid parameters, 403 if write actions are not enabled for the team, 404 for an unknown connector, and 500 for an unexpected error.
Date filtering
You can specify date ranges in two ways:
-
Using
date_preset:https://connectors.windsor.ai/facebook?fields=date,spend&date_preset=last_30d -
Using
date_fromanddate_to:https://connectors.windsor.ai/facebook?fields=date,spend&date_from=2023-01-01&date_to=2023-01-31&api_key={your_api_key}
⚠️ Note: If date_to is not set, the query defaults to today and retrieves the most recent available data up to the current date.
Simple presets
last_7d(last 7 days)last_30d(last 30 days)last_90d(last 90 days)last_year(previous calendar year)
General format
You can also use dynamic presets in the following formats:
last_Xdlast X dayslast_XdTlast X days including todaylast_Xwlast X weekslast_Xmlast X monthslast_Xylast X years
Year based
last_yearprevious calendar yearlast_yearTprevious calendar year including todaylast_2yearslast 2 yearslast_2yearsTlast 2 years including today
Current period
this_monththis monththis_monthTthis month including todaythis_yearthis yearthis_yearTthis year including today
Examples
last_7dlast_30dTlast_3m
Data filtering
Filters use a JSON array format for readability and grouping.
- Each condition is a list:
[field, operator, value] - Combine conditions with
"and"/"or" - Nest lists to group conditions
Supported operators
| Operator | Description | Example |
|---|---|---|
| eq | Equals | [["campaign", "eq", "Summer Sale"]] |
| neq | Not equals | [["campaign", "neq", "Winter Sale"]] |
| gt | Greater than | [["spend", "gt", 100]] |
| gte | Greater or equal | [["spend", "gte", 100]] |
| lt | Less than | [["spend", "lt", 100]] |
| lte | Less or equal | [["spend", "lte", 100]] |
| contains | Contains substring | [["campaign", "contains", "Sale"]] |
| ncontains | Does not contain substring | [["campaign", "ncontains", "Test"]] |
| null | Field is null | [["clicks", "null", null]] |
| notnull | Field is not null | [["clicks", "notnull", null]] |
Examples
⚠️ Note: For actual API requests, URL-encode the
filterparameter. The examples below are shown in plain JSON for readability.
-
Single filter:
https://connectors.windsor.ai/facebook?fields=date,campaign,spend&filter=[["campaign","eq","Summer Sale"]]&api_key={your_api_key}
- Check for null values:
https://connectors.windsor.ai/facebook?fields=date,campaign,clicks&filter=[["clicks","null",null]]&api_key={your_api_key}
-
Multiple conditions (AND):
https://connectors.windsor.ai/facebook?fields=date,spend&filter=[["spend","gt",100],"and",["campaign","contains","Sale"]]&api_key={your_api_key}
-
Nested groups (AND + OR):
https://connectors.windsor.ai/facebook?fields=date,campaign,spend&filter=[[["campaign","eq","foobar"],"or",["spend","eq",10]],"and",["campaign","eq","abc (us)"]]&api_key={your_api_key}
Code examples
import requests
import json
api_key = "your_api_key_here"
connector = "facebook"
fields = "date,campaign,spend"
# Use json.dumps to convert the filter array to JSON string
filter_query = json.dumps([["spend","gt",100],"and",["campaign","contains","Sale"]])
url = f"https://connectors.windsor.ai/{connector}?api_key={api_key}&fields={fields}&filter={filter_query}"
response = requests.get(url)
print(response.json())
Javascript
const apiKey = "your_api_key_here";
const connector = "facebook";
const fields = "date,campaign,spend";
// Convert the filter array to JSON string
const filterQuery = JSON.stringify([["spend","gt",100],"and",["campaign","contains","Sale"]]);
const url = `https://connectors.windsor.ai/${connector}?api_key=${apiKey}&fields=${fields}&filter=${filterQuery}`;
fetch(url)
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error("API error:", err));
Discovering available connectors and fields
Listing all connectors
You can get a list of all available connectors by making a request to:
https://connectors.windsor.ai/list_connectors
This endpoint returns a JSON array of all connectors that are available through the Windsor.ai API.
Retrieving available fields
To see what fields are available for a specific connector, use:
https://connectors.windsor.ai/{connector}/fields
For example, to get all available fields for Facebook:
https://connectors.windsor.ai/facebook/fields
When authenticated with your API key, this endpoint will also return any custom fields that have been configured for your account:
https://connectors.windsor.ai/facebook/fields?api_key={your_api_key}
The response includes detailed information about each field, including:
- Field ID (used in API requests)
- Field name (human-readable name)
- Field type (TEXT, NUMERIC, DATE, etc.)
- Field description
This information is essential for constructing effective API queries and understanding the data structure of each connector.
Connector options
Some connectors support additional configuration options.
These options allow you to customize how data is pulled — such as selecting accounts, toggling breakdowns, choosing report types, or enabling advanced filtering.
This endpoint returns all available options for a specific connector.
Get options for a specific connector
Endpoint
https://connectors.windsor.ai/{connector}/options
Replace {connector} with the connector ID (e.g., facebook, hubspot, salesforce).
Example (Facebook Ads)
Request:
https://connectors.windsor.ai/facebook/options
Example response (simplified):
{ "fields": [ { "key": "account_id", "label": "Ad Account", "type": "dropdown", "required": true, "values": [ { "id": "1234567890", "name": "ACME Ads Account" }, { "id": "9876543210", "name": "Europe Ads Account" } ] }, { "key": "breakdowns", "label": "Breakdowns", "type": "multi_select", "required": false, "values": [ "age", "gender", "country", "placement" ] }, { "key": "level", "label": "Reporting Level", "type": "select", "required": false, "values": [ "ad", "adset", "campaign", "account" ] } ] }
Typical use cases:
- Build a UX for selecting Facebook Ad Accounts or Google Ads Customers
- Display available report types or breakdown options
- Validate user input when generating an authorization or sync configuration
- Dynamically load options for any connector during onboarding
Supported connectors
Windsor.ai supports over 300 connectors, including:
- Social Media: Facebook, Instagram, LinkedIn, Twitter, TikTok, Snapchat, Pinterest
- Search & Display: Google Ads, Microsoft Bing, Google Search Ads, DV360, CM360
- Analytics: Google Analytics 4, Adobe Analytics, Mixpanel, Amplitude
- CRM & Marketing: Salesforce, HubSpot, Marketo, Mailchimp
- E-commerce: Shopify, WooCommerce, Amazon, Stripe
- And many more…
For a complete list of connectors and their specific fields, please refer to our Connectors Directory.
Field types
Fields returned by the API can have the following types:
| Type | Description | Example |
|---|---|---|
TEXT |
Text values | Campaign names, ad titles |
NUMERIC |
Numeric values | Spend, impressions, clicks |
TIMESTAMP |
Date and time values | Date field |
DATE |
Date values | Date field |
BOOLEAN |
Boolean values | True/false flags |
OBJECT |
Complex objects | JSON structures |
Response format
API responses are sent in JSON format:
{
"data": [
{
"date": "2023-01-01",
"spend": 125.45,
"impressions": 10234,
"clicks": 342
},
{
"date": "2023-01-02",
"spend": 134.67,
"impressions": 11456,
"clicks": 389
}
]
}
Error handling
When an error occurs, the API will return an appropriate HTTP status code and a JSON response with error details:
{
"error": {
"code": "authentication_error",
"message": "Invalid API key provided"
}
}
Common error codes:
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | invalid_request |
The request is malformed or missing required parameters |
| 401 | authentication_error |
Invalid API key or authentication credentials |
| 403 | permission_denied |
The API key doesn’t have permission to access the requested resource |
| 404 | not_found |
The requested connector or resource doesn’t exist |
| 429 | rate_limit_exceeded |
Too many requests in a given amount of time |
| 500 | server_error |
An unexpected server error occurred |
Rate limits
API requests are subject to rate limits to ensure fair usage. The current rate limits are:
- 600 requests per minute
- 10,000 requests per day
If you exceed these limits, you’ll receive a 429 status code. The response will include headers indicating your remaining quota and when it will reset.
Renderers
The _renderer parameter specifies the format of the data returned by the Windsor.ai API. Available options include:
- JSON: returns data in JSON format, ideal for web applications and integrations.
https://connectors.windsor.ai/googleanalytics4?api_key=your_api_key&fields=date,spend&_renderer=json - CSV: returns data in CSV format, suitable for spreadsheets and data analysis.
https://connectors.windsor.ai/googleanalytics4?api_key=your_api_key&fields=date,spend&_renderer=csv - Google Sheets: directly imports data into Google Sheets.
https://connectors.windsor.ai/googleanalytics4?api_key=your_api_key&fields=date,spend&_renderer=googlesheets
Default: If no _renderer is specified, the API returns JSON format by default.
Generate authorization link
Windsor.ai provides an endpoint to generate a co-user authorization link. This allows your clients or teammates to connect their data sources without sharing credentials.
You can restrict the link to a single connector or allow any source.
Authorization link for a single data source
Use this endpoint if you want the user to authorize only one specific data source.
https://onboard.windsor.ai/api/team/generate-co-user-url/?allowed_sources={source}&api_key={API_KEY}
Example (LinkedIn Ads only):
https://onboard.windsor.ai/api/team/generate-co-user-url/?allowed_sources=linkedin&api_key=YOUR_API_KEY
This link allows the user to connect only the LinkedIn data source.
Authorization link for any data source
Use this endpoint if you want the user to connect any data source supported by Windsor.ai:
https://onboard.windsor.ai/api/team/generate-co-user-url?api_key={API_KEY}
Example:
https://onboard.windsor.ai/api/team/generate-co-user-url?api_key=YOUR_API_KEY
This link lets the user choose and authorize any available connector.
Co-user linked accounts
These endpoints let you review and manage the accounts that your clients or teammates connected to your team through a co-user authorization link. Use GET to list the linked accounts, and DELETE to unlink one of them.
Endpoint URL:
GET https://onboard.windsor.ai/api/team/co-user-linked-accounts/
DELETE https://onboard.windsor.ai/api/team/co-user-linked-accounts/
Both methods are available to the team owner only. A co-user who signed in through an authorization link cannot list or unlink accounts, and receives 403 Permission denied.
Authentication
You can authenticate your request in two ways:
1. API Key (Recommended for programmatic access): Append your API key to the request using the api_key query parameter.
2. Browser session: The endpoint can be accessed without an API key if the user is actively logged into https://onboard.windsor.ai in the same browser session.
Query parameters
| Parameter | Type | Required | Description |
| api_key | string | Yes* | Your Windsor.ai API key (Not required if making a request from an authenticated browser session). |
| ds_id | string | No | Filter the results by a specific data source ID mysql, facebook_ads, etc.). |
| access_token | string | No | Filter the results by a specific access token. |
Important notes on the response
access_token vs co_user_member_name: The access_token value is only exposed for newly created authentication links. For existing/legacy auth links, the access_token will not be visible, and the co_user_member_name field will be shown instead.
Example requests
1. Basic request (All linked accounts)
HTTP
GET https://onboard.windsor.ai/api/team/co-user-linked-accounts/?api_key=YOUR_API_KEY
2. Filter by data source (ds_id)
To retrieve only linked accounts for a specific data source, such as MySQL:
HTTP
GET https://onboard.windsor.ai/api/team/co-user-linked-accounts/?api_key=YOUR_API_KEY&ds_id=mysql
3. Filter by access token (access_token)
To retrieve details for a specific access token:
HTTP
GET https://onboard.windsor.ai/api/team/co-user-linked-accounts/?api_key=YOUR_API_KEY&access_token=YOUR_ACCESS_TOKEN
Unlink a linked account
Removes an account that was connected through a co-user authorization link from your team. The account is identified by the same values the GET response returns, so the usual flow is: list the linked accounts, pick the one you want to remove, then send a DELETE with its data source and account ID.
Query parameters:
| Parameter | Type | Required | Description |
api_key |
string | Yes* | Your Windsor.ai API key (not required if making a request from an authenticated browser session). |
ds_id |
string | Yes | Data source of the account to unlink (facebook_ads, mysql, etc.). This is the value returned as datasource in the GET response. |
account_id |
string | Yes | The account to unlink, as returned in account_id by the GET response. Account IDs are unique per team and data source. |
access_token |
string | No | Restrict the lookup to the accounts connected through this one authorization link. If the account was not connected through that link, the request returns 404. Legacy links without an access_token cannot be targeted this way, so omit the parameter for those. |
Example requests:
1. Unlink an account
curl -X DELETE "https://onboard.windsor.ai/api/team/co-user-linked-accounts/?api_key=YOUR_API_KEY&ds_id=facebook_ads&account_id=act_123456789"
2. Unlink an account connected through a specific authorization link
curl -X DELETE "https://onboard.windsor.ai/api/team/co-user-linked-accounts/?api_key=YOUR_API_KEY&ds_id=facebook_ads&account_id=act_123456789&access_token=YOUR_ACCESS_TOKEN"
Successful response:
{
"result": "facebook_ads account 'act_123456789' unlinked"
}
What happens when an account is unlinked
- The account is removed from your team, stops appearing in the
GETresponse, and its data is no longer served in connector responses. - For data sources where you pick accounts from a list after authorizing (most OAuth connectors), the account is deselected rather than erased. The authorization stays in place, so you can select the account again in the Windsor.ai app without asking for a new authorization link.
- For all other data sources the stored account record is deleted, and reconnecting it requires a new authorization.
- The authorization link itself is not revoked, and the other accounts connected through the same link stay connected. To remove several accounts, send one request per account.
- The connection in the co-user’s own Windsor.ai team is not affected.
Response codes:
| Code | Meaning |
| 200 | The account was unlinked. |
| 400 | ds_id or account_id is missing, or the data source rejected the removal. The reason is in the error field. |
| 403 | The API key does not belong to the team owner. |
| 404 | No linked account matches the given ds_id and account_id, for example because it was already unlinked, or because it does not belong to the access_token you scoped the request to. |
Example error response:
{
"error": "Linked account not found"
}
Connector connect info
This endpoint describes how a data source can be connected to your Windsor.ai account: whether it authorizes via OAuth or manual credentials, a ready-to-use connect URL, and the credential fields required for manual connectors. Use it to build connection flows into your own tools, apps or AI assistants.
Get connect info for a data source
Endpoint:
https://onboard.windsor.ai/api/mcp/connectors/{connector}/connect-info?api_key={your_api_key}
Replace {connector} with the connector ID (e.g., facebook, google_ads, klaviyo). Same IDs as in the data API.
| Parameter | Type | Required | Description |
| connector | string | Yes | The data source ID, passed in the URL path. |
| api_key | string | Yes* | Your Windsor.ai API key (not required if making a request from an authenticated browser session). |
Response fields
| Field | Type | Description |
| connector | string | The connector ID you requested. |
| auth_type | string | oauth for connectors authorized via the provider’s consent screen; manual for connectors that require credentials entered by the user (e.g. an API key from the platform). |
| connect_url | string | A temporary sign-in link that opens the right connection screen: the provider’s authorization flow (OAuth) or the connector’s setup form (manual). |
| fields | array | For manual connectors, the credential fields required. Empty for OAuth connectors. |
Each entry in fields has:
| Field | Type | Description |
| name | string | Field identifier, e.g. account_name, api_key. |
| type | string | string, integer or boolean. |
| required | boolean | Whether the field must be provided. |
| sensitive | boolean | true for secrets (passwords, tokens, API keys). |
Example responses
OAuth connector:
{ "connector": "facebook", "auth_type": "oauth", "connect_url": "https://onboard.windsor.ai/token-login?access_token={temporary_token}&next=/facebook/authorize", "fields": [] }
Manual connector:
{ "connector": "klaviyo", "auth_type": "manual", "connect_url": "https://onboard.windsor.ai/token-login?access_token={temporary_token}&next=/app/klaviyo", "fields": [ { "name": "account_name", "type": "string", "required": true, "sensitive": false }, { "name": "api_key", "type": "string", "required": true, "sensitive": true } ] }
Important notes
The connect_url contains a temporary access token that signs in to your Windsor.ai account. Treat it like a password: do not share it or store it in logs. The link expires automatically after 4 days; request the endpoint again to get a fresh one. Fields marked “sensitive”: true are secrets (passwords, tokens, API keys). Never display or log values entered for these fields. Requesting an unknown connector ID returns a 404 error.
List connected accounts
This endpoint returns all data source accounts connected to your Windsor.ai workspace.
You can query a specific data source or request all accounts.
List accounts for all data sources
Endpoint:
https://onboard.windsor.ai/api/common/ds-accounts?datasource=all
Example response (simplified):
[ { "datasource": "google_ads", "account_name": "ACME Google Ads", "account_id": "123-456-7890", "status": "active" }, { "datasource": "facebook", "account_name": "ACME Facebook Ads", "account_id": "987654321", "status": "active" } ]
List accounts for a specific data source
Endpoint:
https://onboard.windsor.ai/api/common/ds-accounts?datasource={SOURCE}
Example (Facebook Ads data source):
https://onboard.windsor.ai/api/common/ds-accounts?datasource=facebook
Returns only Facebook Ads accounts connected to the workspace.
Custom fields API
This endpoint returns custom fields defined in your Windsor.ai workspace.
These fields can be used in queries or enrichments across supported data sources.
List all custom fields
Endpoint:
https://onboard.windsor.ai/api/custom-fields
These fields are available immediately after creation and can be referenced in API queries.
Example use cases
Retrieving campaign performance
https://connectors.windsor.ai/facebook?fields=date,campaign,spend,impressions,clicks&date_preset=last_30d&api_key={your_api_key}
Comparing multiple platforms
https://connectors.windsor.ai/all?fields=date,source,spend,impressions,clicks&date_preset=last_30d&api_key={your_api_key}
Getting e-commerce conversion data
https://connectors.windsor.ai/googleanalytics4?fields=date,campaign,transactions,revenue&date_preset=last_30d&api_key={your_api_key}
Best practices
- Request only needed fields
- Use date presets when possible
- Implement caching
- Always handle errors with care
User agent
When making API requests to Windsor.ai connectors, the system identifies itself using the following user agent:
Windsor/1.0
This user agent is automatically included in all API requests made through our official SDKs and libraries. If you’re building custom integrations or directly interacting with our API, we recommend including this user agent in your requests for better tracking and support.
Support
If you encounter any issues or have questions about using our API, please contact our support team at [email protected] or visit our Help Center.
Changelog
2026-07-27
- Unlinking of co-user linked accounts added
2026-07-03
- Connector connect-info endpoint added
2026-02-24
- Co-user linked accounts endpoint added
2025-11-13
- Creation of authorization links added
2025-04-02
- Added information about different renderers
2025-03-18
- Added information about the user agent
2025-03-17
- Initial API documentation release
Windsor vs Coupler.io