This page explains how to use our API to start AI Visibility runs and fetch their results.
All requests to our API should be authenticated. Our API is RESTful and communicates using JSON.
Start a new AI Visibility run
Method: POST
Endpoint: https://api.insites.com/api/v1/ai-visibility
Request body should be JSON encoded, and can include the following fields:
Property | Definition | Required |
business_name | String – The name of the business to check. | Yes |
city | String – The business’s city. | Yes |
country_code | String – Two-letter ISO country code, e.g. GB. | Yes |
category | String – The business category, e.g. Plumber. | Yes |
phone | String – The business’s phone number. | No |
website | String – The business’s website. | No |
language_code | String – Language code for the run, e.g. | No |
engines | String array – A list of engines to run. Supported values are chatgpt, gemini, grok and perplexity. If omitted, all engines will run. | No |
on_completion | String – An https:// URL we’ll send the finished run to when it completes. | No |
new_business | Boolean – If true, creates a new business record instead of reusing an existing business with the same website. | No |
queries | Array – The complete set of questions this run and later runs should use. Between one and five questions can be supplied. These replace any questions already saved for the business rather than being added to them. If the run cannot start, the existing questions remain unchanged. | No |
Example
curl "https://api.insites.com/api/v1/ai-visibility" \
--header "api-key:[YOUR API KEY]" \
--header "Content-Type: application/json" \
--data
'{"business_name": "Acme Plumbing",
"city": "Leeds",
"country_code": "GB",
"category": "Plumber",
"website": "acme.test"}'
Expected response
If successful, you would expect a 202 response, with a body like this:
{"id": "9f2c1a7b8e4d4c10a3b25f6e7d8c9012",
"status": "pending",
"business":
{"id": "7d4e9b2a1c8f4063b5e2a9d7c1f60384",
"created": true}}The response also includes a Location header pointing to the new run, which can be used to fetch the run status.
All possible responses
Code | Reason |
202 | Accepted. The run has started. |
402 | The account doesn’t have enough credits to start the run. |
403 | This action is not permitted with the API credentials you are using. |
409 | A run is already in progress for this business. |
422 | The request could not be processed. |
Start an AI Visibility run for an existing business
Method: POST
Endpoint: https://api.insites.com/api/v1/businesses/[BusinessID or ReportID]/ai-visibility
The request body is optional. If no request body is sent, all engines will run.
If request body is supplied, it should be JSON encoded and can include the following fields.
Property | Definition | Required |
engines | String array – A list of engines to run. Supported values are chatgpt, gemini, grok and perplexity. If omitted, all engines will run. | No |
on_completion | String – An https:// URL we’ll send the finished run to when it completes. | No |
queries | Array – The complete replacement set of questions for this business. Between one and five questions can be supplied. If the run cannot start, the existing questions remain unchanged. See Manage the questions below. | No |
Example
curl "https://api.insites.com/api/v1/businesses/7d4e9b2a1c8f4063b5e2a9d7c1f60384/ai-visibility"\
--header "api-key:[YOUR API KEY]" \
--header "Content-Type: application/json" \
--data '{"engines": ["chatgpt", "perplexity"]}'
Expected response
If successful, you would expect a 202 response, with a body like this:
{"id": "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d",
"status": "pending",
"business": {
"id": "7d4e9b2a1c8f4063b5e2a9d7c1f60384",
"created": false}}
All possible responses
Code | Reason |
202 | Accepted. The run has started. |
402 | The account doesn’t have enough credits to start the run. |
403 | This action is not permitted with the API credentials you are using. |
404 | Business not found. |
409 | A run is already in progress for this business. |
422 | The request could not be processed. |
Fetch a specific AI Visibility run
Method: GET
Endpoint: https://api.insites.com/api/v1/ai-visibility/[ID]
Example
curl "https://api.insites.com/api/v1/ai-visibility/9f2c1a7b8e4d4c10a3b25f6e7d8c9012"\
--header "api-key:[YOUR API KEY]"
Expected response
If the run is still processing, you would expect a 202 response, with a body like this:
{"id": "9f2c1a7b8e4d4c10a3b25f6e7d8c9012",
"status": "processing",
"started_at": "2026-06-24T09:15:02Z",
"completed_at": null,
"business":
{"id": "7d4e9b2a1c8f4063b5e2a9d7c1f60384",
"name": "Acme Plumbing",
"website": "acme.test"},
"links": {
"self": "https://api.insites.com/api/v1/ai-visibility/9f2c1a7b8e4d4c10a3b25f6e7d8c9012",
"rerun": "https://api.insites.com/api/v1/businesses/7d4e9b2a1c8f4063b5e2a9d7c1f60384/ai-visibility"}}If the run has completed, you would expect a 200 response with the completed run data.
All possible responses
Code | Reason |
200 | Run details returned. |
202 | The run is still processing. |
404 | Run not found. |
Fetch a list of AI Visibility runs
Method: GET
Endpoint: https://api.insites.com/api/v1/ai-visibility
Returns a list of AI Visibility runs for your account, newest first. The request can include the following filters:
Property | Definition | Required |
business_name | String – Partial, case-insensitive match on the business name. | No |
url | String – Partial, case-insensitive match on the business website. | No |
status | String – Only return runs with this status. Supported values are pending, processing, completed and failed. | No |
created_after | String – Only return runs created at or after this date-time. | No |
created_before | String – Only return runs created before this date-time. | No |
sort | String – Sort field. Prefix with - for descending. Defaults to -created_at. | No |
limit | Integer – Number of runs per page. Defaults to 25. | No |
offset | Integer – Number of runs to skip. Defaults to 0. | No |
Example
curl "https://api.insites.com/api/v1/ai-visibility?status=completed&limit=10"\
--header "api-key:[YOUR API KEY]"
Expected response
If successful, you would expect a 200 response, with a body like this:
{"data": [{
"id": "9f2c1a7b8e4d4c10a3b25f6e7d8c9012",
"status": "completed",
"started_at": "2026-06-24T09:15:02Z",
"completed_at": "2026-06-24T09:17:48Z",
"business": {
"id": "7d4e9b2a1c8f4063b5e2a9d7c1f60384",
"name": "Acme Plumbing",
"website": "acme.test"},
"links": {
"self": "https://api.insites.com/api/v1/ai-visibility/9f2c1a7b8e4d4c10a3b25f6e7d8c9012",
"rerun": "https://api.insites.com/api/v1/businesses/7d4e9b2a1c8f4063b5e2a9d7c1f60384/ai-visibility"
}}],
"meta": {
"total": 1,
"limit": 10,
"offset": 0
}}
All possible responses
Code | Reason |
200 | List of AI Visibility runs. |
400 | An invalid filter was supplied. |
Fetch a list of AI Visibility runs for a business
Method: GET
Endpoint: https://api.insites.com/api/v1/businesses/[BusinessID or ReportID]/ai-visibility
Returns a list of AI Visibility runs for a specific business, newest first. The request can include the following filters:
Property | Definition | Required |
limit | Integer – Number of runs per page. Defaults to 25. | No |
offset | Integer – Number of runs to skip. Defaults to 0. | No |
Example
curl "https://api.insites.com/api/v1/businesses/7d4e9b2a1c8f4063b5e2a9d7c1f60384/ai-visibility"\
--header "api-key:[YOUR API KEY]"
All possible responses
Code | Reason |
200 | List of AI Visibility runs returned. |
404 | Business not found. |
Manage the questions
Every AI Visibility run scores a business against a set of questions: an unbranded question, such as “Who’s the best plumber in Leeds?”, and a branded question, such as “Is Acme Plumbing any good?”, for each topic.
Every engine in a run is asked the same questions, and later runs reuse the same set. This makes results comparable between engines and over time.
Changes take effect on the next run. Editing questions does not change the results of a run that has already completed.
If you do not provide questions, we generate a set from the business’s category when its first run starts and reuse it for later runs. A business can have up to five questions.
[BusinessID or ReportID] can be the business ID returned in a run’s business object, or a report ID.
Fetch a business’s questions
Method: GET
Endpoint: https://api.insites.com/api/v1/businesses/[BusinessID or ReportID]/ai-visibility/queries
Returns the questions used for the business’s AI Visibility runs.
An empty data list is expected if the business has not completed an AI Visibility run and questions have not been added manually.
Example
curl "https://api.insites.com/api/v1/businesses/7d4e9b2a1c8f4063b5e2a9d7c1f60384/ai-visibility/queries" \ --header "api-key:[YOUR API KEY]"
Expected response
If successful, you would expect a 200 response with a body like this:
{ "data": [ { "id": "3f9a1c4e7b2d48a6905e1f8c2b7d4e60", "topic": "emergency callouts", "recommendation_query": "who does 24 hour emergency plumbing in Leeds", "reputation_query": "is Acme Plumbing reliable in an emergency?", "language_code": "en_GB", "ai_generated": true } ], "meta": { "max": 5 } }ai_generated is true when the question was generated automatically and has not been edited.
All possible responses
Code | Reason |
| The current questions were returned. |
| AI Visibility is not enabled for this account. |
| No business matches the supplied business ID or report ID for this account. |
Replace a business’s questions
Method: PUT
Endpoint: https://api.insites.com/api/v1/businesses/[BusinessID or ReportID]/ai-visibility/queries
Replaces the business’s complete set of questions. Any existing question not included in the request will be removed.
Request body should be JSON encoded and include the following fields:
Property | Definition | Required |
| Array – The complete set of questions. Between one and five questions can be supplied. | Yes |
| String – A short label describing the topic, e.g. | Yes |
| String – The unbranded question asked when someone is looking for this type of business. Maximum 255 characters. | Yes |
| String – The branded question asked about the business by name. Maximum 255 characters. | Yes |
| String – The language used for the question, e.g. | No |
At least one question is required. To remove the complete set, use the delete endpoint described below.
Example
curl --request PUT "https://api.insites.com/api/v1/businesses/7d4e9b2a1c8f4063b5e2a9d7c1f60384/ai-visibility/queries" \ --header "api-key:[YOUR API KEY]" \ --header "Content-Type: application/json" \ --data '{ "queries": [ { "topic": "emergency callouts", "recommendation_query": "who does 24 hour emergency plumbing in Leeds", "reputation_query": "is Acme Plumbing reliable in an emergency?" }, { "topic": "boiler servicing", "recommendation_query": "best boiler service engineers in Leeds", "reputation_query": "what do people say about Acme Plumbing boiler work?" } ] }'
Expected response
If successful, you would expect a 200 response containing the complete saved set in the same format as the fetch endpoint.
All possible responses
Code | Reason |
| The complete set of questions was replaced. |
| AI Visibility is not enabled for this account. |
| No business matches the supplied business ID or report ID for this account. |
| One or more fields could not be processed. The |
Update a question
Method: PATCH
Endpoint: https://api.insites.com/api/v1/businesses/[BusinessID or ReportID]/ai-visibility/queries/[QuestionID]
Updates one question without changing the rest of the set.
[QuestionID] is the question’s id returned by the fetch endpoint. The request can include topic, recommendation_query, reputation_query or language_code. At least one field must be supplied.
Example
curl
--request PATCH "https://api.insites.com/api/v1/businesses/7d4e9b2a1c8f4063b5e2a9d7c1f60384/ai-visibility/queries/3f9a1c4e7b2d48a6905e1f8c2b7d4e60" \ --header "api-key:[YOUR API KEY]" \
--header "Content-Type: application/json" \
--data '{ "recommendation_query": "emergency plumber near me Leeds" }'
Expected response
If successful, you would expect a 200 response containing the updated question.
All possible responses
Code | Reason |
| The question was updated. |
| AI Visibility is not enabled for this account. |
| No business matches the supplied reference, or the question does not belong to that business. |
| No recognised field was supplied, a field exceeds its length limit or the |
Delete a question
Method: DELETE
Endpoint: https://api.insites.com/api/v1/businesses/[BusinessID or ReportID]/ai-visibility/queries/[QuestionID]
Deletes one question without changing the rest of the set.
Example
curl
--request DELETE "https://api.insites.com/api/v1/businesses/7d4e9b2a1c8f4063b5e2a9d7c1f60384/ai-visibility/queries/3f9a1c4e7b2d48a6905e1f8c2b7d4e60" \
--header "api-key:[YOUR API KEY]"
All possible responses
Code | Reason |
| The question was deleted. There is no response body. |
| AI Visibility is not enabled for this account. |
| No business matches the supplied reference, or the question does not belong to that business. |
Delete all questions for a business
Method: DELETE
Endpoint: https://api.insites.com/api/v1/businesses/[BusinessID or ReportID]/ai-visibility/queries
Deletes every question currently saved for the business. The next run will generate a new set from the business’s category. Deleting the questions for a business that does not currently have any questions will still succeed.
Example
curl
--request DELETE "https://api.insites.com/api/v1/businesses/7d4e9b2a1c8f4063b5e2a9d7c1f60384/ai-visibility/queries" \
--header "api-key:[YOUR API KEY]"
All possible responses
Code | Reason |
| All questions were deleted. There is no response body. |
| AI Visibility is not enabled for this account. |
| No business matches the supplied business ID or report ID for this account. |
Webhooks
If an on_completion URL is supplied when starting a run, we will POST the finished run to that URL once it reaches a final status.
Example payload
{
"id": "evt_9f2c1a7b8e4d4c10a3b25f6e7d8c9012",
"type": "run.completed",
"timestamp": "2026-06-24T09:17:48Z",
"data": {
"...": "the full run, exactly as returned by GET /ai-visibility/[ID]"
}}Respond with a 2xx status to acknowledge the webhook. Other responses are logged but not retried.
Webhook event types
Type | Reason |
run.completed | The AI Visibility run has completed. |
run.failed | The AI Visibility run failed. |
Verifying the signature
If you’ve configured a webhook signing secret in your API settings, each webhook delivery will include a Webhook-Signature header.
Example
Webhook-Signature: t=1718450042,v1=5257a869e7...
The signature is a lowercase hex HMAC-SHA256 hash of:
<timestamp>.<raw-request-body>
To verify a webhook:
Read
t(timestamp) andv1(signature) from the header.Recompute the HMAC using
t + "." + body, using the raw request body and your signing secret.Compare your value to
v1using a constant-time comparison.
Optionally, reject requests whose timestamp is older than your chosen tolerance (for example, five minutes) to help prevent replay attacks. If no signing secret is configured, webhooks are sent unsigned.
Idempotency
To make retries safe, send an Idempotency-Key header when starting a run.
If we receive a repeated request carrying the same key within 24 hours, we return the original run instead of starting a new one.
Example
curl "https://api.insites.com/api/v1/ai-visibility"\
--header "api-key:[YOUR API KEY]"\
--header "Idempotency-Key: 7c3e1f08-2b9a-4d6e-9f1a-1c2d3e4f5a6b"\
--header "Content-Type: application/json"\
--data
'{"business_name": "Acme Plumbing",
"city": "Leeds",
"country_code": "GB",
"category": "Plumber"
}'
Pagination
The list endpoints support pagination using limit and offset.
Property | Definition |
limit | The number of runs to return per page. Defaults to 25. |
offset | The number of runs to skip. Defaults to 0. |
Each response includes a meta object with the total count, and a links object with pagination URLs for self, first, prev, next and last.
Errors
Errors are returned as JSON.
Example error
{"type": "about:blank",
"title": "A run is already in progress",
"status": 409,
"detail": "This business already has a run in progress.",
"code": "run_in_progress"}On a validation error, the response also includes an errors list with the specific fields at fault.
Example validation error
{
"type": "about:blank",
"title": "Validation failed",
"status": 422,
"detail": "One or more fields are invalid.",
"code": "validation_failed",
"errors": [
{
"field": "country_code",
"code": "required",
"detail": "country_code is required."
}
]
}
Error codes
Code | Status | Reason |
insufficient_credits | 402 | The account doesn’t have enough credits to start the run. |
not_permitted | 403 | This action is not permitted with the API credentials you are using. |
business_not_found | 404 | No business matches the supplied business ID or report ID for this account. |
query_not_found | 404 | No question with that ID belongs to this business. |
run_not_found | 404 | The requested run could not be found. |
run_in_progress | 409 | A run is already in progress for this business. |
validation_failed | 422 | One or more request fields are invalid. |
insufficient_business_data | 422 | The business details supplied are not enough to run a check. |
invalid_engines | 422 | One or more of the requested engines is not recognised. |
invalid_filter | 400 | A search filter was invalid. |
Completed run data
A completed run from GET https://api.insites.com/api/v1/ai-visibility/[ID] includes the following sections:
Property | Definition |
id | The AI Visibility run ID. |
status | The current run status. |
started_at | The date and time the run started. |
completed_at | The date and time the run completed. |
business | The business linked to the run. |
links | API links for the run. |
readiness | AI readiness checks for the business. |
engines | Results from each AI engine. |
insights | Summary insights and recommended fixes. |
Run statuses
Status | Definition |
pending | The run has been created and is waiting to start. |
processing | The run is in progress. |
completed | The run has completed successfully. |
failed | The run could not be completed. |
OpenAPI specification
A full machine-readable OpenAPI specification is available for this API.
You can import it into tools like Postman or Insomnia to explore the endpoints and generate client code.
