Everything the portal does by hand, a request can do too, the same frameworks, the same rulings, the same clause-level reasoning. Two calls take an asset from upload to verdict.
A human still makes the call. The API hands them the clause, the reason and the fix, already on the page.
01
Submit the assets
POST /v1/evaluations as multipart form data: a name, the frameworks to judge against, and the files themselves. The evaluation id comes back immediately.
02
Poll the evaluation
GET /v1/evaluations/{evaluationId} returns the batch's status and, once it is completed, the section-by-section ruling for every asset in it.
03
Zoom into one asset
Each file in a batch is a job. GET /v1/jobs/{id} reads a single one back on its own, with the clause each finding cites.
04
Work with what is already there
Frameworks, assets and uploads are reachable too; list what you can judge against, browse the media already in the workspace, or send a large file straight to storage.
Authentication
One key, one header
Keys are workspace-scoped and made in the portal under Settings → API keys. Every v1 route reads the same header; a bearer token is the web session's and will not work here.
Every request
X-API-Key: $VOXLY_API_KEY
Reference
17 endpoints
Frameworks are read-only: they are authored, versioned and approved in the portal, and the API reads their ids and sections back.
Usage
GET/v1/usage
Returns this workspace's current credit usage and balance.
Use this to show the current plan, consumption during its billing period, and the remaining balance including any top-ups.
Request
curl -X GET "https://api.voxlyvision.com/api/v1/usage" \
-H "X-API-Key: $VOXLY_API_KEY"
Starts an evaluation of one or more assets against the frameworks you name.
Multipart, not JSON, the assets can travel in the same request. Repeat the frameworkIds and the selected asset-source field to send more than one. Choose exactly one asset source: files, uploadIds, assetIds, or fileUrls. Do not combine them in the same request. Each option is shown below. The work is queued: the response returns as soon as it is accepted, and each asset becomes its own job. Limits are 5 assets and 3 frameworks per request, 500 MB per file.
Parameters
namestringrequired
Labels the batch in the workspace.
frameworkIdsuuid[]required
One field per framework the assets are judged against, 3 at most. Get the ids from GET /v1/frameworks.GET /v1/frameworks →
Choose exactly one asset source
filesfile[]optional
The assets themselves. One field per file, 5 per request, 500 MB each.Content types →
uploadIdsuuid[]optional
Instead of files. Ids from POST /v1/uploads whose bytes you already sent to storage; the evaluation completes the upload for you.POST /v1/uploads →
assetIdsuuid[]optional
Instead of files. Re-runs assets already in the workspace; nothing is uploaded and they keep their folder.GET /v1/assets →
fileUrlsstring[]optional
Instead of files. Public https urls Voxly Vision downloads itself, http is refused, as are private, loopback and link-local addresses. 500 MB per file, 8192 characters per url.
labelIduuidoptional
Files newly created assets into a folder. Ignored for assetIds re-runs, which keep the folder they already have.
idempotencyKeyuuidoptional
Reusing one returns the original batch instead of running, and charging, twice.
5 ways to call this
Send the file with the request
The simplest form. The asset is uploaded and evaluated in one call.
For large media. Request an upload url; PUT the bytes to storage, then name the uploadId here, the evaluation turns it into an asset for you, so the completion call is not needed.
Reads the whole batch back, the status of the evaluation and the results of every job in it.
This is the endpoint to poll. While work is outstanding the status stays pending or processing; once it reads completed, every job carries its section results. A job that could not be evaluated reports failed with a failureCode.
Parameters
evaluationIduuidrequired
Path parameter. The id returned by POST /v1/evaluations.
Request
curl -X GET "https://api.voxlyvision.com/api/v1/evaluations/{evaluationId}" \
-H "X-API-Key: $VOXLY_API_KEY"
Reads one job, a single asset's ruling, section by section, with the reasoning behind each one.
A job is one asset inside an evaluation. Each section result carries a classification, the justification for it, a recommendation where one applies, and the framework section it was judged against.
Parameters
iduuidrequired
Path parameter. A jobId from the evaluation's jobs array.
Request
curl -X GET "https://api.voxlyvision.com/api/v1/jobs/{id}" \
-H "X-API-Key: $VOXLY_API_KEY"
Response
{
"jobId": "b7d4c2f1-90ae-4d63-8c25-1a6f7e930bd4",
"status": "completed",
"assetId": "3c9a1b70-52d8-4e11-bb7f-6d2c8a4f1e93",
"assetName": "spring-campaign-hero.jpg",
"results": [
{
"resultId": "9e5b3d21-7c48-4a6f-b0d9-2f8e1c4a6b57",
"status": "completed",
"frameworkId": "1f0c2a94-6b4f-4b3d-9a2c-0f4d5e6a7b81",
"frameworkName": "Portman",
"classification": "non_compliant",
"justification": "Clause 3.2(b), the drinking scene precedes the product shot.",
"voxlyInsights": null,
"error": null,
"sections": [
{
"sectionId": "5a2c7e90-3b16-4d82-9f4a-8c0e5b7d1a63",
"sectionTitle": "Consumption",
"subsectionTitle": "Order of depiction",
"classification": "non_compliant",
"justification": "The pour is shown before the pack shot.",
"recommendation": "Re-cut so the product is established first."
}
]
}
]
}
DELETE/v1/jobs/{id}
Deletes a job and the ruling it produced.
The asset the job ran on is left alone, deleting a job removes the evaluation of it, not the media. Delete the asset separately if you want both gone.
Lists the media in the workspace, newest or oldest first.
Answers with a bare array rather than a paginated envelope, so there is no total to read, ask for the next page until one comes back with fewer rows than the limit. Defaults are page 1, limit 10, oldest first.
Parameters
pagenumberoptional
1-based. Defaults to 1.
limitnumberoptional
Rows per page. Defaults to 10.
orderstringoptional
Sorts by upload date. Defaults to asc.ascdesc
qstringoptional
Filters by file name, case-insensitive substring.
labelIdsstringoptional
Comma-separated folder ids. An asset matching any of them is returned.
ownedbooleanoptional
Restricts the list to assets this API key uploaded.truefalse
3 ways to call this
Newest first
The first page of the library, most recent upload first.
Request
curl -X GET "https://api.voxlyvision.com/api/v1/assets?page=1&limit=10&order=desc" \
-H "X-API-Key: $VOXLY_API_KEY"
Search by file name
Substring match, case-insensitive. Remember to url-encode the term.
Request
curl -X GET "https://api.voxlyvision.com/api/v1/assets?q=spring&order=desc" \
-H "X-API-Key: $VOXLY_API_KEY"
One folder, uploaded by this key
Folder ids are asset-scope labels; the portal calls them folders.
Request
curl -X GET "https://api.voxlyvision.com/api/v1/assets?labelIds=7b2e9c04-1f83-4a55-9d61-0c8e3b5a2f47&owned=true" \
-H "X-API-Key: $VOXLY_API_KEY"
Metadata only, the media itself is not served here. `createdBy` is whichever principal uploaded it: a user id for a portal upload, an API key id for one of yours.
Parameters
iduuidrequired
Path parameter. An assetId from a list, an upload completion, or a job.
Request
curl -X GET "https://api.voxlyvision.com/api/v1/assets/{id}" \
-H "X-API-Key: $VOXLY_API_KEY"
Lists the frameworks this workspace can evaluate against, its own and the global ones.
One row per framework family, carrying whichever version is current. Use the frameworkId to read, update a draft, or approve a framework; use frameworkGroupId to create its next version. Live frameworkIds are what you pass to frameworkIds when you start an evaluation.
Ask for live unless you have a reason not to, a draft or deprecated framework is not something to judge against.pendingprocessingdraftlivedeprecatedfailedFramework status →
2 ways to call this
Everything you can evaluate against
The usual call: live frameworks, both the global codes and this workspace's own.
Request
curl -X GET "https://api.voxlyvision.com/api/v1/frameworks?status=live" \
-H "X-API-Key: $VOXLY_API_KEY"
This workspace's own frameworks
Custom frameworks only, authored in the portal.
Request
curl -X GET "https://api.voxlyvision.com/api/v1/frameworks?type=custom&status=live" \
-H "X-API-Key: $VOXLY_API_KEY"
Reads one framework in full, including every section an evaluation will judge against.
The sections are the framework's substance: each carries the rules text, whether it applies to every asset, and the description that decides applicability when it does not. This is the endpoint to read if you want to explain a ruling in your own interface.
Parameters
iduuidrequired
Path parameter. A frameworkId from the list endpoint.
Request
curl -X GET "https://api.voxlyvision.com/api/v1/frameworks/{id}" \
-H "X-API-Key: $VOXLY_API_KEY"
Response
{
"frameworkId": "1f0c2a94-6b4f-4b3d-9a2c-0f4d5e6a7b81",
"frameworkName": "Portman",
"description": "UK alcohol advertising code.",
"frameworkGroupId": "8d3e5f27-1a94-4c60-b8f2-7e0a1d5c9b34",
"type": "global",
"version": 3,
"isLatest": true,
"status": "live",
"createdAt": "2026-05-19T11:03:21.884Z",
"updatedAt": "2026-07-02T16:40:07.552Z",
"sections": [
{
"sectionId": "5a2c7e90-3b16-4d82-9f4a-8c0e5b7d1a63",
"sectionTitle": "Consumption",
"subsectionTitle": "Order of depiction",
"rules": "The product must be established before consumption is shown.",
"alwaysApplicable": true
}
]
}
POST/v1/frameworks
Creates a custom framework from sections you provide.
The framework starts as a draft. Define at least one section, then approve it when it is ready to evaluate against. Custom is the default frameworkType; global frameworks are reserved for authorised administrators.
Parameters
namestringrequired
The framework's display name.
industrystringrequired
The industry this framework covers, for example general or alcohol.
marketsstring[]required
One to ten markets, such as global, united_kingdom, or united_states. global cannot be combined with another market.
sectionsobject[]optional
The rules to evaluate. The object schema is detailed below.
sections[].sectionTitlestringrequired
Title of this rule section.
sections[].rulesstringrequired
The rules Voxly Vision should evaluate against.
sections[].alwaysApplicablebooleanrequired
true when this section applies to every asset; otherwise false.
sections[].subsectionTitlestringoptional
Optional subheading within the section.
sections[].applicabilityDescriptionstringoptional
Optional explanation of when a section that is not always applicable should apply.
descriptionstringoptional
Optional explanation of the framework.
Create a draft framework
Supply the rules in the request, then approve the returned frameworkId when it is ready.
Request
curl -X POST "https://api.voxlyvision.com/api/v1/frameworks" \
-H "X-API-Key: $VOXLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Brand safety","industry":"general","markets":["global"],"description":"Internal marketing guidance.","sections":[{"sectionTitle":"Truthful claims","rules":"Claims must be accurate and substantiated.","alwaysApplicable":true}]}'
Creates a framework by fetching a document from the web.
API framework upload currently supports web_upload only. Send a public document URL in frameworkUrl; file_upload and multipart PDF uploads are not supported through this API at this time. The response is pending while the document is processed into sections.
Parameters
namestringrequired
The framework's display name.
industrystringrequired
The industry this framework covers, for example general or alcohol.
marketsstring[]required
One to ten markets. global cannot be combined with another market.
uploadMethodstringrequired
Must be web_upload. file_upload is not currently supported via the API.
frameworkUrlstringrequired
Public URL of the framework document Voxly Vision should fetch.
supplementalDomainsstring[]optional
Optional supporting domains, up to three.
Upload from a public document URL
web_upload is the only API upload method today; do not send a file or s3Key.
Pass the frameworkGroupId from a framework response as id, not the frameworkId. A new version preserves prior evaluations on their original version; a live current version is superseded and the new version starts as a draft when sections are supplied.
Parameters
iduuidrequired
Path parameter. The frameworkGroupId of the family to version.
sectionsobject[]optional
Replacement rules for the new version. The object schema is detailed below.
sections[].sectionTitlestringrequired
Title of this rule section.
sections[].rulesstringrequired
The rules Voxly Vision should evaluate against.
sections[].alwaysApplicablebooleanrequired
true when this section applies to every asset; otherwise false.
sections[].subsectionTitlestringoptional
Optional subheading within the section.
sections[].applicabilityDescriptionstringoptional
Optional explanation of when a section that is not always applicable should apply.
Optional replacements for the family metadata; omitted fields keep their current values.
Revise its rules
Use the frameworkGroupId returned by the list or detail response.
Request
curl -X POST "https://api.voxlyvision.com/api/v1/frameworks/{id}/versions" \
-H "X-API-Key: $VOXLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"description":"Updated rules for 2026","sections":[{"sectionTitle":"Truthful claims","rules":"Claims must be accurate, current and substantiated.","alwaysApplicable":true}]}'
Use this for a draft's name, industry, markets, description, or supplemental domains. An approved (live) framework cannot be updated; create a new version instead, which preserves evaluations against the approved version.
Asks for a presigned url so you can send a file straight to storage.
Step one of three. Describe the file here, PUT the bytes to the uploadUrl that comes back, then either call the completion endpoint or pass the uploadId to POST /v1/evaluations, which completes it for you. Large media never passes through the API this way. The url expires, so request it when you are ready to send.
Parameters
fileNamestringrequired
The name the asset will carry in the workspace.
contentTypestringrequired
Must match what you actually PUT to the url.image/jpegimage/pngvideo/mp4text/plainContent types →
fileSizenumberrequired
Bytes, up to 500 MB. Declared up front so the url can be signed for it.
3 ways to call this
An image
A 2 MB png. The response carries the url to PUT it to.
Turns a finished upload into an asset in the workspace.
Step three, and optional: call it once the PUT has succeeded to get the asset back, or skip it entirely and pass the uploadId to POST /v1/evaluations, which completes the upload itself. There is no request body.
Parameters
uploadIduuidrequired
Path parameter, from POST /v1/uploads. No body is required.
Request
curl -X POST "https://api.voxlyvision.com/api/v1/uploads/{uploadId}/complete" \
-H "X-API-Key: $VOXLY_API_KEY"