Ad Validation API
Ad Screenshots API
Ad Optimizer API
Ad Server Vendors
Ad Ops Teams
Large Publishers
HTML5 Designers
vpn_keyGet API Key
codeGithub PHP Class
menu_bookAPI Documentation
person_outlineMy Account
chat_bubble_outlineHelp & Support
CreativeQA.io
Ad Validation Made Easy
menu

API v3.0 Introduction

Your API Endpoint

https://{your_name}.api.creativeqa.net

Your secret tool to save yourself hours on troubleshooting advertisement issues ;)

Use the API to automatically scan creatives pre-flight. The API is organized around REST, and returns JSON for all responses.

Getting an API Key

To get your API Key, log in to your account and go to REST API Key in the menu. If you haven't signed up yet, you can do so here.

Authentication

Add your API Key as a header

# Add the Authorization header to each request
curl "https://{your_name}.api.creativeqa.net"
  -H "X-ApiKey: {api_key}"
  -X POST

API Keys are used to authenticate requests. Add your key to each request as a header with the name X-ApiKey. Keep your API key private as much as you do with passwords.

Rate Limits

Rate limits are calculated dynamically based on the load of the worker nodes. If no resources are available, the API will respond with a 400 HTTP code and an error message. It's generally recommended to wait for a response before sending a new one. To process batches of tags, submit them one by one instead of all at the same time.

Error Handling

Example of an error

{
    "error_type": "payload_error",
    "message": "There was an error."
}

Conventional HTTP response codes are used to indicate if a request failed or was successful. Codes in the 2xx range indicate success. Codes in the 4xx range indicate that the request failed. In that case, the JSON response will hold an error code and human-readable error message.

Error Types

authentication_error
string, solvable
The X-ApiKey header was not added or the key was incorrect. Contact support if you need help.
license_error
string, solvable
Your license has not been approved or has expired. Contact support for more information.
invalid_endpoint
string, solvable
An incorrect endpoint URL was used. Check for typos and make sure to use the endpoints from this documentation.
payload_error
string, solvable
The payload contained missing parameters or had an incorrect format. See the error message for details.
timeout
string, solvable
It took too long for the creative to load. Increase the default timeout manually if you wish to run the scan for a longer time.
processing_error
string, not solvable
The worker nodes weren't able to process your request. Please drop us a note to see if we could troubleshoot.

Change Log

Changes to the API are generally backwards compatible. If non-backwards compatible changes are introduced, the API version number in your endpoint URL will go up. Once you've reviewed the changelog and made the necessary changes at your side, you're invited to use the new API version by updating your endpoint URL accordingly.

HTML5 Zip Validator

Run a new scan

curl "https://{your_name}.api.creativeqa.net/v3.0/scan/zip"
  -H "X-ApiKey: {api_key}"
  -X POST
  -d '{
    "data": "WW91ciB6aXAgYmluYXJ5IGhlcmUuLi4="
}'

Example response

{
    "3pas": "",
    "blocked_by_adblock": false,
    "click_tag_found": true,
    "console": {
        "errors": ["Error: ReferenceError: somefunction is not defined"],
        "warnings": []
    },
    "cookies": [{
        "domain": ".creativeqa.io",
        "expires": 1646483649,
        "httpOnly": false,
        "name": "__gads",
        "path": "/",
        "priority": "Medium",
        "secure": false,
        "session": false,
        "size": 92,
        "value": "ID=1a98edadd0995906-22cd64eb62ba0089:T=1612787649:S=ALNI_MYy4JVsyP7DbDydn73L6WR0-fHnKA"
    },
    {
        "domain": ".doubleclick.net",
        "expires": 1646483650.085365,
        "httpOnly": true,
        "name": "IDE",
        "path": "/",
        "priority": "Medium",
        "sameSite": "None",
        "secure": true,
        "session": false,
        "size": 70,
        "value": "AHWqTUlqh0OPFbGUeGXQqkXebE_Tf9xEs0i7fspXWBfoQHL0p3ooP5Iv-vx7JYmWKsA"
    }],
    "cpu_usage": 66,
    "creative_rendered": true,
    "dialogs": [],
    "dimensions": {
        "height": 90,
        "width": 728
    },
    "dom_content_loaded": 162,
    "file_structure": [{
        "bytes": 3922,
        "name": "front_city.png",
        "type": "image"
    },
    {
        "bytes": 11860,
        "name": "index.html",
        "type": "html"
    },
    {
        "bytes": 6510,
        "name": "google_logo.png",
        "type": "image"
    }],
    "has_border": false,
    "has_external_assets": false,
    "has_video": false,
    "iframes": 1,
    "local_storage": [],
    "memory_usage": 2400256,
    "meta": {
        "api_version": "v3.0",
        "cpu": "AMD 16-Core EPYC 7302P",
        "creative_type": "zip",
        "device": "Desktop",
        "language": "en-US",
        "ram": "128GB",
        "scan_duration": "1.871964",
        "server_location": "ams",
        "timestamp": 1612789956,
        "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
    },
    "meta_ad_size": false,
    "minified": true,
    "mobile_friendly": false,
    "network": {
        "load_size": {
            "host_initiated_subload": 0,
            "initial_load": 35690,
            "total": 35690
        },
        "responses": [{
            "bytes": 11860,
            "headers": {
                "content-encoding": "br",
                "content-type": "text/html",
                "date": "Mon, 08 Feb 2021 13:12:34 GMT",
                "last-modified": "Sat, 18 Apr 2020 18:08:16 GMT"
            },
            "is_pixel": false,
            "method": "GET",
            "resource_type": "document",
            "server_ip": "127.0.0.1",
            "ssl": true,
            "ssl_info": {
                "protocol": "TLS 1.3",
                "validFrom": 1607455037,
                "validTo": 1922815037
            },
            "status": 200,
            "status_text": "",
            "timing": 169,
            "url": "https://www.creativeqa.io/tmp/7febf-e5693-1b71c-78616.zip/index.html"
        },
        {
            "bytes": 6510,
            "headers": {
                "accept-ranges": "bytes",
                "content-length": "6510",
                "content-type": "image/png",
                "date": "Mon, 08 Feb 2021 13:12:34 GMT",
                "last-modified": "Sat, 18 Apr 2020 18:08:16 GMT"
            },
            "is_pixel": false,
            "method": "GET",
            "resource_type": "image",
            "server_ip": "127.0.0.1",
            "ssl": true,
            "ssl_info": {
                "protocol": "TLS 1.3",
                "validFrom": 1607455037,
                "validTo": 1922815037
            },
            "status": 200,
            "status_text": "",
            "timing": 201,
            "url": "https://www.creativeqa.io/tmp/7febf-e5693-1b71c-78616.zip/google_logo.png"
        },{
            "..."
        }]
    },
    "job_id": "7febf-e5693-1b71c-78616",
    "screenshot": {
        "highres": {
            "bytes": 132,
            "color": "#d8ecfe",
            "mime_type": "image/png",
            "url": "https://try.cdn.creativeqa.net/img/qa-report-983243-29cbfuzn4mhk.png"
        },
        "thumbnail": {
            "bytes": 538,
            "color": "#d8ecfe",
            "mime_type": "image/jpg",
            "url": "https://try.cdn.creativeqa.net/img/qa-report-983243-xz5rs8mc3yuk.jpg"
        }
    },
    "ssl": {
        "compliant": true,
        "insecure_urls": []
    },
    "uses_document_write": false,
    "visual_artifacts": false,
    "json": {
        "url": "https://try.cdn.creativeqa.net/img/qa-report-983243-4n9vhsar26uk.json"
    }
}

Use this scan to validate HTML5 ads in Zip format. Add the binary Zip file as a base64-encoded string to your API request.

Endpoint

POST https://{your_name}.api.creativeqa.net/v3.0/scan/zip

Arguments

data
string, required
The binary Zip file in base64-encoded format. The maximum size for this string is 10 MB.
targeting
array
An array with targeting settings that will be applied before loading the creative. It can contain these key/values:
  • device either desktop or mobile
  • language the HTTP accept-header, like en-US

Returns

3pas
string
The name of the third-party ad server, if detected successfully. Remains blank otherwise.
blocked_by_adblock
boolean
Whether or not the tag will likely be blocked by ad blockers.
click_tag_found
boolean
Whether or not a click tag was found in the index.html file.
console
array
All errors and warnings generated while loading the creative.
cookies
array
All cookies that were dropped by the creative, either set via JavaScript or via an HTTP header.
cpu_usage
int
The CPU usage, in milliseconds.
creative_rendered
boolean
Equals true in case something was painted on the screen, false otherwise.
dialogs
array
Any dialog message the creative shows as a pop-up. Generally created by alert() and confirm().
dimensions
array
The detected width and height of the creative.
dom_content_loaded
int
The time it took for the DOMContentLoaded event to fire, in milliseconds.
file_structure
array
Contains the file structure of the Zip, including the name, type and file size.
has_border
boolean
Whether or not the creative has a contrasting border.
has_external_assets
boolean
Whether or not the creative loads assets from outside the Zip. Keep this at a minimum to reduce additional DNS lookups, connections, etc.
has_video
boolean
Whether or not the creative plays video content.
iframes
int
The number of iframes added to the DOM. This should be kept at a minimum to reduce memory usage.
local_storage
array
All key/value pairs stored in window.localStorage.
memory_usage
int
The amount of RAM memory used, in bytes.
meta
array
Meta-data about the scan, like the CPU used, the time it took to complete the scan, the server location, etc.
meta_ad_size
boolean
Whether or not the index file has a <meta name="ad.size" content="width=X,height=X"> line, as per IAB standards.
minified
boolean
Whether or not all CSS and JavaScript files were minified. Returns false if at least one file was found where more than 5% savings were possible, true otherwise.
mobile_friendly
boolean
Whether or not the creative will display fine on a mobile device. Equals true if the creative is either responsive or less than 300 pixels wide.
network
array
All network requests and their responses, including a full echo of the HTTP headers. Provides SSL certificate information too.
job_id
string
A unique ID assigned to the scan. Store this ID on your own backend to re-fetch result data at a later moment.
screenshot
array
A screenshot of the creative. The url points to a PNG image. The background_color is in hex-format. It generally goes well with the main colors of the screenshot.
ssl
boolean
Whether or not the creative is SSL-compliant. If the creative tries to load assets over http, it will equal false.
uses_document_write
boolean
Whether or not the creative uses the JS document.write() function. Synchronous code should be avoided.
visual_artifacts
boolean
If visual artifacts have been detected. For example, a 300x250 creative that is actualy 301x251 in size.
json
array
The url contains a link to the JSON result of the scan. Great for manual downloads and inspection.

Retrieve a scan

curl "https://{your_name}.api.creativeqa.net/v3.0/jobs/{job_id}"
  -H "X-ApiKey: {api_key}"
  -X GET

Example response

{
    "3pas": "",
    "blocked_by_adblock": false,
    "click_tag_found": true,
    "..."
}

To retrieve a cached JSON response of a creative you've previously scanned, use the following endpoint. Make sure to use GET as a method. The job_id can be found in the response from a new scan.

Endpoint

GET https://{your_name}.api.creativeqa.net/v3.0/jobs/{job_id}

Returns

response
object
The full JSON response from the original scan.

Ad Tag Validator

Run a new scan

curl "https://{your_name}.api.creativeqa.net/v3.0/scan/tag"
  -H "X-ApiKey: {api_key}"
  -X POST
  -d '{
    "data": "WW91ciBhZCB0YWcgaGVyZS4uLg=="
}'

Example response

{
    "3pas": "Google Ad Manager (GAM)",
    "blocked_by_adblock": true,
    "console": {
        "errors": ["Error: ReferenceError: somefunction is not defined"],
        "warnings": []
    },
    "cookies": [{
        "domain": ".creativeqa.io",
        "expires": 1646483649,
        "httpOnly": false,
        "name": "__gads",
        "path": "/",
        "priority": "Medium",
        "secure": false,
        "session": false,
        "size": 92,
        "value": "ID=1a98edadd0995906-22cd64eb62ba0089:T=1612787649:S=ALNI_MYy4JVsyP7DbDydn73L6WR0-fHnKA"
    },
    {
        "domain": ".doubleclick.net",
        "expires": 1646483650.085365,
        "httpOnly": true,
        "name": "IDE",
        "path": "/",
        "priority": "Medium",
        "sameSite": "None",
        "secure": true,
        "session": false,
        "size": 70,
        "value": "AHWqTUlqh0OPFbGUeGXQqkXebE_Tf9xEs0i7fspXWBfoQHL0p3ooP5Iv-vx7JYmWKsA"
    }],
    "cpu_usage": 634,
    "creative_rendered": true,
    "dialogs": [],
    "dimensions": {
        "height": 250,
        "width": 300
    },
    "dom_content_loaded": 166,
    "has_border": true,
    "has_video": false,
    "iframes": 2,
    "local_storage": [],
    "memory_usage": "11313152",
    "meta": {
        "api_version": "v3.0",
        "cpu": "AMD 16-Core EPYC 7302P",
        "creative_type": "ad_tag",
        "device": "Desktop",
        "language": "en-US",
        "ram": "128GB",
        "scan_duration": "2.809499",
        "server_location": "ams",
        "timestamp": 1612787651,
        "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
    },
    "mobile_friendly": true,
    "network": {
        "load_size": {
            "host_initiated_subload": 0,
            "initial_load": 263515,
            "total": 263515
        },
        "responses": [{
            "bytes": 19175,
            "headers": {
                "cache-control": "private, max-age=900, stale-while-revalidate=3600",
                "content-encoding": "gzip",
                "content-length": "19175",
                "content-type": "text/javascript",
                "date": "Mon, 08 Feb 2021 12:34:09 GMT",
                "etag": "\"777 / 11 of 1000 / last-modified: 1612786878\"",
                "expires": "Mon, 08 Feb 2021 12:34:09 GMT",
                "server": "sffe",
                "timing-allow-origin": "*",
                "vary": "Accept-Encoding",
            },
            "is_pixel": false,
            "method": "GET",
            "resource_type": "script",
            "server_ip": "142.250.179.194",
            "ssl": true,
            "ssl_info": {
                "protocol": "TLS 1.3",
                "validFrom": 1611043025,
                "validTo": 1618300624
            },
            "status": 200,
            "status_text": "",
            "timing": 172,
            "url": "https://securepubads.g.doubleclick.net/tag/js/gpt.js"
        },
        {
            "bytes": 103509,
            "headers": {
                "accept-ranges": "bytes",
                "cache-control": "private, immutable, max-age=31536000",
                "content-encoding": "gzip",
                "content-length": "103509",
                "content-type": "text/javascript",
                "cross-origin-resource-policy": "cross-origin",
                "date": "Mon, 08 Feb 2021 12:34:09 GMT",
                "expires": "Mon, 08 Feb 2021 12:34:09 GMT",
                "last-modified": "Tue, 02 Feb 2021 09:38:25 GMT",
                "server": "sffe",
                "timing-allow-origin": "*",
                "vary": "Accept-Encoding",
            },
            "is_pixel": false,
            "method": "GET",
            "resource_type": "script",
            "server_ip": "142.250.179.194",
            "ssl": true,
            "ssl_info": {
                "protocol": "TLS 1.3",
                "validFrom": 1611043025,
                "validTo": 1618300624
            },
            "status": 200,
            "status_text": "",
            "timing": 224,
            "url": "https://securepubads.g.doubleclick.net/gpt/pubads_impl_2021020201.js"
        },{
            "..."
        }]
    },
    "job_id": "2af21-de8d9-7cb57-8f014",
    "screenshot": {
        "highres": {
            "bytes": 37715,
            "color": "#77b2c1",
            "mime_type": "image/png",
            "url": "https://try.cdn.creativeqa.net/img/qa-report-983243-aue7bczw9t3v.png"
        },
        "thumbnail": {
            "bytes": 3460,
            "color": "#77b2c1",
            "mime_type": "image/jpg",
            "url": "https://try.cdn.creativeqa.net/img/qa-report-983243-6gn25mbhxwu9.jpg"
        }
    },
    "ssl": {
        "compliant": true,
        "insecure_urls": []
    },
    "uses_document_write": false,
    "visual_artifacts": false,
    "json": {
        "url": "https://try.cdn.creativeqa.net/img/qa-report-983243-txkf9dmzawu7.json"
    }
}

Use this scan to validate ad tags in HTML and/or JavaScript. Add the ad tag as a base64-encoded string to your API request.

Endpoint

POST https://{your_name}.api.creativeqa.net/v3.0/scan/tag

Arguments

data
string, required
The ad tag in base64-encoded format.
targeting
array
An array with targeting settings that will be applied before loading the ad tag. It can contain these key/values:
  • device either desktop or mobile
  • language the HTTP accept-header, like en-US
  • country either usa or nld
  • page_url the URL on which the ad tag will be tested

Returns

3pas
string
The name of the third-party ad server, if detected successfully. Remains blank otherwise.
blocked_by_adblock
boolean
Whether or not the tag will likely be blocked by ad blockers.
console
array
All errors and warnings generated while loading the creative.
cookies
array
All cookies that were dropped by the creative, either set via JavaScript or via an HTTP header.
cpu_usage
int
The CPU usage, in milliseconds.
creative_rendered
boolean
Equals true in case something was painted on the screen, false otherwise.
dialogs
array
Any dialog message the creative shows as a pop-up. Generally created by alert() and confirm().
dimensions
array
The detected width and height of the creative.
dom_content_loaded
int
The time it took for the DOMContentLoaded event to fire, in milliseconds.
has_border
boolean
Whether or not the creative has a contrasting border.
has_video
boolean
Whether or not the creative plays video content.
iframes
int
The number of iframes added to the DOM. This should be kept at a minimum to reduce memory usage.
local_storage
array
All key/value pairs stored in window.localStorage.
memory_usage
int
The amount of RAM memory used, in bytes.
meta
array
Meta-data about the scan, like the CPU used, the time it took to complete the scan, the server location, etc.
mobile_friendly
boolean
Whether or not the creative will display fine on a mobile device. Equals true if the creative is either responsive or less than 300 pixels wide.
network
array
All network requests and their responses, including a full echo of the HTTP headers. Provides SSL certificate information too.
job_id
string
A unique ID assigned to the scan. Store this ID on your own backend to re-fetch result data at a later moment.
screenshot
array
A screenshot of the creative. The url points to a PNG image. The background_color is in hex-format. It generally goes well with the main colors of the screenshot.
ssl
boolean
Whether or not the creative is SSL-compliant. If the creative tries to load assets over http, it will equal false.
uses_document_write
boolean
Whether or not the creative uses the JS document.write() function. Synchronous code should be avoided.
visual_artifacts
boolean
If visual artifacts have been detected. For example, a 300x250 creative that is actualy 301x251 in size.
json
array
The url contains a link to the JSON result of the scan. Great for manual downloads and inspection.

Retrieve a scan

curl "https://{your_name}.api.creativeqa.net/v3.0/jobs/{job_id}"
  -H "X-ApiKey: {api_key}"
  -X GET

Example response

{
    "3pas": "",
    "blocked_by_adblock": false,
    "..."
}

To retrieve a cached JSON response of a creative you've previously scanned, use the following endpoint. Make sure to use GET as a method. The job_id can be found in the response from a new scan.

Endpoint

GET https://{your_name}.api.creativeqa.net/v3.0/jobs/{job_id}

Returns

response
object
The full JSON response from the original scan.

Software Development Kits

PHP Class (Github)

Here's a PHP Class that makes implementation a bit easier:
https://github.com/CreativeQA/ad-validator-php