Introduction
New Try the API Explorer. Browse every endpoint, read its parameters and responses, and issue live calls against your own account without writing any code.
It is generated from /api/openapi.json, which is derived from the API's own behaviour rather than written by hand, so unlike this page it cannot fall behind what the API actually does.
The ads.txt Guru API allows you to control your account programmatically, this enables you to manage your domains, groups and ads.txt records using your own code, and most importantly enables you to streamline publisher aquisition by integrating the domain invite process into your publisher control panel.
HTTPS connections are used (HTTP connections are not permitted). These HTTPS connections are made to different URIs depending on the API function required, all of which must include the API protocol version. The API response is by default provided in JSON format, however the response can optionally be provided in PHP serialize() format, and optionally encoded using base64 encoding.
Every endpoint accepts POST. The endpoints that read one of your own objects also accept GET, and each endpoint below states which methods it takes directly under its name. validate/adstxt, validate/sellersjson and compare/adstxt are POST only despite changing nothing, because the file you send them does not fit in a URL. If you are writing new code, sending everything by POST always works and needs no reference to that list.
All API requests require your API key and secret which can be found under the Integrate section of your ads.txt Guru account. We recommend sending them as the X-API-Key and X-API-Secret request headers rather than as parameters, so that your credentials never appear in a URL (see Authentication).
This API also describes itself. An OpenAPI document covering every endpoint, parameter and response is published at /api/openapi.json (YAML), generated from the API's own behaviour rather than written by hand, so a client generator can consume it and it cannot fall behind this page. You can browse the same document, and issue live calls against your own account, in the API Explorer.
Note, we will be providing language specific libraries to simplify integration, beginning with a PHP library in the near future. Please contact us for more information.
If you have any questions regarding API integration, please contact us.
# Example listing domains
curl https://adstxt.guru/api/1.0/domain/list/
-d key=KEY
-d secret=SECRET
# Example response
{
"success": true,
"domains": {
"1234": {
"id": "1234",
"tag": "abcdefgi01234567",
"name": "domain.com",
"protocol": "https",
"verify_key": "ABCDEFGU01234567",
"verified": "0",
"comment": "1",
"synchronize": "0",
"discovery": "1"
}
}
}
$api = atg_api('KEY', 'SECRET');
Authentication
API authentication is handled using your API key and secret, these are required for all API requests. Your API key and secret can be found under the Integrate section of your ads.txt Guru account.
API access must be enabled in the Integrate section of your ads.txt Guru account in order to access the API.
Your credentials may be sent either as the X-API-Key and X-API-Secret request headers, or as the key and secret parameters. Headers are recommended. Parameters sent on a GET request travel in the URL, where they are recorded in web server access logs, in the logs of any intermediate proxy, and in a Referer header, so a long lived credential can end up in places you did not intend. The header form keeps the credential out of the URL whichever HTTP method you use. The parameters remain supported and are not being withdrawn without notice.
If both are supplied then the headers are used and the parameters are ignored. Both headers must be present to be used as a pair, otherwise the parameters are read as before.
If your request has failed authentication then a 401 HTTP status code will be returned.
Headers
| X-API-Key: | string (recommended) Your 32 character API key. |
| X-API-Secret: | string (recommended) Your 32 character API secret. |
Parameters
| key: | string (required if the X-API-Key header is not sent) Your 32 character API key. |
| secret: | string (required if the X-API-Secret header is not sent) Your 32 character API secret. |
| format: | string json, json64, serial or serial64. |
# Example request, credentials in headers (recommended)
curl https://adstxt.guru/api/1.0/
-H "X-API-Key: KEY"
-H "X-API-Secret: SECRET"
# Example request, credentials as parameters
curl https://adstxt.guru/api/1.0/
-d key=KEY
-d secret=SECRET
# Example authentication failed response
{
"success": false,
"reason": "authentication"
}
$api = atg_api('KEY', 'SECRET');
Responses & Errors
API responses are provided as arrays, either in JSON or PHP serialize() format.
The success value will always be included as true or false depending on the success of the request. The reason value will be returned when a request has not been successful, the core reasons are authentication, disabled and invalid, further reasons will be returned for specific functions.
API requests will typically be returned with a 200 HTTP status code, a 401 code will be returned when authentication has failed, a 400 code will be returned if the request was invalid, and a 429 code will be returned when the request has been rate limited (see Rate Limiting).
Unsuccessful reasons
| authentication: | Authentication has failed. |
| disabled: | API access is disabled in the Integrate section of your ads.txt Guru account. |
| invalid: | Request is invalid, either URI or parameters are incorrect. |
| rate-limit: | Too many requests for this API key within the rate limit window. See Rate Limiting. |
| maintenance: | API currently unavailable due to maintenance. |
| discontinued: | API protocol version no longer supported. |
# Example request
curl https://adstxt.guru/api/1.0/invalid/
-d key=KEY
-d secret=SECRET
# Example invalid request response
{
"success": false,
"reason": "invalid"
}
$api = atg_api('KEY', 'SECRET');
Rate Limiting
Heavyweight API endpoints are rate limited per API key to protect the service from accidental traffic bursts. Currently applies to validate/adstxt, validate/sellersjson and compare/adstxt. The two validate endpoints share their ceilings: wherever validate/adstxt is named below, a validate/sellersjson call with the same parameter counts against the same ceiling.
The window is 30 seconds, rolling, and what you may send inside it depends on how much work the call makes us do. validate/adstxt called with data is 150 calls per window per API key: it parses a file you already have, and fetches nothing. The two that fetch are 30 calls per window each, counted separately: compare/adstxt, which retrieves every domain you list, and validate/adstxt called with url, which retrieves the file itself.
There is a second ceiling on top of that one, and it is the first one expressed per second: 5 calls per second for validate/adstxt with data, and 1 call per second for the two that fetch. It takes away nothing you are allowed to send, because 150 per 30 seconds is 5 a second and 30 per 30 seconds is 1. What it stops is sending a window's worth all at once, which costs us far more than the same calls spread out and slows down every other client while it lands. If you pace at or below the per-second figure for the endpoint you are calling, you will never meet it.
A heavy paste caller therefore still has its full 30 fetches. When either is exceeded, the API returns a 429 HTTP status code with a rate-limit reason, and the headers below report the ceiling for the call you just made. If you have a legitimate use case that requires more, get in touch.
These ceilings are floors, not caps. They are what your key is guaranteed whatever else is happening, and we never serve you less. When the service has spare capacity we lend it out, so a call past your ceiling may be served instead of refused. A call served that way carries X-RateLimit-Surplus: 1, and only such a call carries it: the header is absent, never 0, on a call inside your own ceilings. On a borrowed call one of the Remaining headers reads 0 while the call still succeeds, which is how to tell it apart. Spare capacity is shared by every caller and moves with load from second to second, so treat a borrowed call as a loan rather than a new limit. Keep pacing to X-RateLimit-Burst, which always states your own ceiling and never the surplus: a client that raises its rate because a run of calls succeeded will meet 429s the moment the capacity it borrowed is needed elsewhere. When there is nothing to lend, you get exactly the ceilings above and a 429 past them.
The cheapest call is the one you do not make. Every compare/adstxt response carries a Cache-Control: private, max-age of its own, and that number is not a guess: it is the shortest time still left on the copies of the publisher files that answered the call, so it states exactly how long the body stays true. A client that honours it will not re-ask a question whose answer cannot have changed yet, which keeps it under both ceilings above without any pacing logic at all. It reads private because the body carries your own results and your own token balance, so it must never be held by a shared cache.
The two rate limited endpoints include these headers on every response, so a well-behaved client can pace itself rather than wait to be refused. No other endpoint emits them.
Response Headers
| X-RateLimit-Limit: | integer Number of calls per window your key is guaranteed. |
| X-RateLimit-Remaining: | integer Calls remaining in the current window after this request. |
| X-RateLimit-Window-Seconds: | integer Length of the rate limit window in seconds. |
| X-RateLimit-Reset: | integer Unix timestamp at which the oldest call in the current window will expire and free up capacity. |
| X-RateLimit-Burst: | integer Number of calls in a single second your key is guaranteed, regardless of how much of the window above is unused. |
| X-RateLimit-Burst-Remaining: | integer Calls remaining in the current second after this request. |
| X-RateLimit-Burst-Window-Seconds: | integer Length of the burst window in seconds. |
| X-RateLimit-Surplus: | integer (only on a borrowed call) Always 1 when present. The call was past one of your ceilings and was served from spare capacity instead of refused. Absent on every other response. It says nothing about what you may send next, so keep pacing to X-RateLimit-Burst. |
| Retry-After: | integer (only on 429) Seconds to wait before retrying. This is the only header here defined by a standard (RFC 9110), and the one to build your retry logic on: it always names the wait for whichever ceiling refused the call. |
429 Response Body
| success: | boolean Always false for a rate-limit response. |
| reason: | string Always rate-limit, whichever ceiling refused the call. |
| ceiling: | string Which ceiling refused: sustained (the window) or burst (the single second). The limit, window_seconds, reset_unix and retry_after_seconds fields below all describe that ceiling, so you do not need to read this to retry correctly. |
| message: | string Human-readable explanation of the limit. |
| limit: | integer Maximum number of calls permitted per window. |
| remaining: | integer Always 0 in a rate-limit response. |
| window_seconds: | integer Length of the rate limit window in seconds. |
| reset_unix: | integer Unix timestamp at which the oldest call in the current window will expire. |
| retry_after_seconds: | integer Seconds to wait before retrying. |
# Example rate limited response headers
HTTP/2 429
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0
X-RateLimit-Window-Seconds: 30
X-RateLimit-Reset: 1715763600
X-RateLimit-Burst: 16
X-RateLimit-Burst-Remaining: 0
X-RateLimit-Burst-Window-Seconds: 1
Retry-After: 17
# Example rate limited response body
{
"success": false,
"reason": "rate-limit",
"ceiling": "sustained",
"message": "Too many requests for this API key. Limit is 30 calls per 30 seconds.",
"limit": 30,
"remaining": 0,
"window_seconds": 30,
"reset_unix": 1715763600,
"retry_after_seconds": 17
}
# The same refusal from the BURST ceiling. Note Retry-After is 1, not 17:
# you are inside your window allowance, you just sent it too fast.
{
"success": false,
"reason": "rate-limit",
"ceiling": "burst",
"message": "Too many requests for this API key. Limit is 16 calls per 1 second.",
"limit": 16,
"remaining": 0,
"window_seconds": 1,
"reset_unix": 1715763584,
"retry_after_seconds": 1
}
$api = atg_api('KEY', 'SECRET');
Paying for Calls
The stateless tools, validate/adstxt, validate/sellersjson and compare/adstxt, are paid for with tokens, bought in advance in the Integrate section of your account. No plan is needed: tokens alone are enough for those, on a free Basic account or on no subscription at all.
The rest of the API, the operations over your own domains, groups and records, is not metered at all, but it does need a plan that includes API access. Today that means the Ad Network plan: a Basic or Publisher account calling one of those endpoints is refused with a 403 and a subscription reason, whether or not it holds tokens.
If your plan already includes API access, nothing is metered for you and you do not need tokens at all, not even for the stateless tools. An Ad Network subscription covers the whole API, and calls made on it are never charged against a balance. Every authenticated response tells you which side of this you are on: X-Tokens-Metered: 0 means a subscription is covering the call.
Verify your email address and we credit 1,000 tokens, once, so you can build against the API before deciding anything. Tokens are valid for 365 days from your most recent purchase, and are sold to businesses only. The rates below are the rates we charge; the API Token Terms are the contract they sit under.
Token Cost
| validate/adstxt with data | 1 token You hand us the file, so there is no outbound request to make. |
| validate/adstxt with url | 2 tokens We fetch the file from the address you give us, then parse it. |
| validate/sellersjson with data | 1 token You hand us the file, so there is no outbound request to make. |
| validate/sellersjson with url | 2 tokens We fetch the file from the domain you give us, following the specification's redirect rules, then check it. |
| compare/adstxt | 1 token per domain in domains Every entry in your list is a separate request we make to that domain's web server, so a call carrying a thousand domains costs us a thousand times what one carrying a single domain does. |
| Your own domains and groups | 0 tokens Not metered, but gated on an Ad Network plan rather than on tokens. |
A call is charged when it runs, not when it succeeds. A domain that does not resolve, times out or serves nothing still costs us the request, so a stale list costs you real tokens. Knowing the weight of a job before you send it is the point of pricing this way.
What you are never charged for is work we did not do. A domain we decline to fetch, because it resolves to a private or reserved address, and one we ran out of time to reach before the call ended, are both settled back out of the cost. compare/adstxt answers with tokens_charged and tokens_not_charged so the reconciliation arrives with the results, beside the per-domain reason saying which were skipped and why. X-Tokens-Cost and X-Tokens-Balance state the settled figures, not the figures the call reserved, so a client pacing itself on those headers is reading the truth.
One compare/adstxt call carries at most 100 domains. That is the same limit for every caller, whatever your plan and whatever your balance: holding enough tokens for a longer list does not let you send it in a single request. Over the cap, nothing is fetched and nothing is charged - the call is refused with a domains-limit reason whose body states the cap as limit and what you sent as domains. Split a longer list across several calls; there is no cap on how many calls make up a job, only on the size of one.
Every authenticated response carries X-Tokens-Metered, and every metered call also carries its cost and your remaining balance, so a client can pace itself rather than wait to be refused.
Response Headers
| X-Tokens-Metered: | integer 1 if this key pays per call, 0 if a subscription covers it. Present on every authenticated response. |
| X-Tokens-Cost: | integer (metered calls only) Tokens this call cost. |
| X-Tokens-Balance: | integer (metered calls only) Tokens remaining after this call. |
402 Response Body
A call your balance will not cover is refused with a 402 HTTP status code and a tokens reason. Nothing is charged and nothing is run, so the work can be retried unchanged once the balance is topped up.
| success: | boolean Always false for a token response. |
| reason: | string Always tokens. |
| cost: | integer Tokens the refused call would have cost. |
| balance: | integer Tokens you hold. |
| shortfall: | integer Tokens you are short by, so a client can size a top-up without arithmetic. |
# Example metered response headers
HTTP/2 200
X-Tokens-Metered: 1
X-Tokens-Cost: 3
X-Tokens-Balance: 9997
# Example 402 response body
{
"success": false,
"reason": "tokens",
"cost": 3,
"balance": 2,
"shortfall": 1
}
$api = atg_api('KEY', 'SECRET');
Domain
The domain functions allow you to manage the domains which would normally be managed under the Manage section of your ads.txt Guru account.
These functions give you complete control to add, edit and remove your domains.
Domain data is provided in what we refer to as the Domain Array which includes the domain values as outlined below.
Domain Array
| id: | integer Numeric domain ID. |
| tag: | string 16 character domain tag. |
| name: | string The domain name. |
| protocol: | string The domain protocol, either https or http. |
| file: | string The file this domain manages, either ads.txt or app-ads.txt. Every URL associated with the domain refers to this file: the verification target, the hosted URL, the download filename. The same domain name may be added once for each file, giving you two independent domains with separate verification, delivery configuration and version history; this is the model the app-ads.txt standard itself describes. The file is fixed when the domain is added. |
| verify_key: | string 16 character domain verification key. |
| verified: | integer 0 if domain has not been verified, 1 if domain has been verified. |
| verify_version: | string The # Version header observed in the domain's live ads.txt at the last verification check, or an empty string if our header was absent. Advisory only — it never affects verified. |
| comment: | integer 0 if comments will not be included in generated ads.txt file, 1 if comments will be included. |
| synchronize: | integer 1 if automatic synchronization is enabled (requires 'Connect FTP' or 'Connect WordPress' is configured), 0 if not enabled. |
| discovery: | integer 1 if domain can be discovered using domain tag, 0 if discovery is disabled. |
# Example domain array
{
"id": "1234",
"tag": "abcdefgi01234567",
"name": "domain.com",
"protocol": "https",
"file": "ads.txt",
"verify_key": "ABCDEFGU01234567",
"verified": "0",
"verify_version": "",
"comment": "1",
"synchronize": "0",
"discovery": "1"
}
$api = atg_api('KEY', 'SECRET');
domain/list
GET or POST
This function allows you to retrieve a list of all domains under your account.
Successful response values
| success: | boolean true |
| domains: |
array An array of Domain Arrays, each array record uses the domain ID as it's key. |
# Example request
curl https://adstxt.guru/api/1.0/domain/list/
-d key=KEY
-d secret=SECRET
# Example successful response
{
"success": true,
"domains": {
"1234": {
"id": "1234",
"tag": "abcdefgi01234567",
"name": "domain.com",
"protocol": "https",
"verify_key": "ABCDEFGU01234567",
"verified": "0",
"comment": "1",
"synchronize": "0",
"discovery": "1"
},
"1235": {
"id": "1235",
"tag": "abcdefgi01234568",
"name": "another.com",
"protocol": "http",
"verify_key": "ABCDEFGU01234568",
"verified": "1",
"comment": "1",
"synchronize": "1",
"discovery": "1"
}
}
}
$api = atg_api('KEY', 'SECRET');
domain/add
POST
This function allows you to add a new domain to your account.
Parameters
| protocol: | string https or http. |
| name: | string (required) The domain name to be added, excluding the protocol. e.g. domain.com |
| file: | string ads.txt (default) or app-ads.txt. Adding an app-ads.txt domain requires a plan that includes app-ads.txt support. A domain name you already hold as ads.txt can be added again as app-ads.txt. The two are independent domains, and the pair only counts once against your domain allowance. |
Unsuccessful reasons
| invalid: | Invalid name, protocol or file value. |
| duplicate: | Domain has already been added under this account for this file. The same name for the other file is not a duplicate. |
| conflict: | Domain has already been added under another account. This applies to both files: another account holding a name for either file blocks it for both. |
| permission: | Your plan does not include app-ads.txt support. Only returned for file=app-ads.txt. |
| limit: | Maximum domains limit reached. The limit counts domain names, so a name held for both files uses one. |
Successful response values
| success: | boolean true |
| domain: |
array Domain Array. |
| first_domain: | boolean true when this was the first domain on the account, otherwise false. Useful for triggering onboarding in your own integration. |
# Example request
curl https://adstxt.guru/api/1.0/domain/add/
-d key=KEY
-d secret=SECRET
-d protocol=https
-d name=domain.com
-d file=ads.txt
# Example duplicate domain response
{
"success": false,
"reason": "duplicate"
}
# Example successful response
{
"success": true,
"domain": {
"id": "1234",
"tag": "abcdefgi01234567",
"name": "domain.com",
"protocol": "https",
"file": "ads.txt",
"verify_key": "ABCDEFGU01234567",
"verified": "0",
"comment": "1",
"synchronize": "0",
"discovery": "1"
},
"first_domain": true
}
$api = atg_api('KEY', 'SECRET');
domain/get
GET or POST
This function allows you to retrieve a specific domain under your account.
In addition to the standard Domain Array fields, this function returns the time of the last verification check (verify_time, a unix timestamp) and an advisory version-currency signal. version_current is the ads.txt version we currently publish for the domain; version_status compares it against the version observed in the live ads.txt at the last check (verify_version) and is one of current (the live file is up to date), behind (we re-checked after publishing and the live file is still serving an older version — a stale copy), or unknown (not verified, or not yet re-checked since your last change, so we make no claim — a freshly edited domain reads unknown until the next check rather than falsely reporting behind). version_match is a convenience boolean, true only when version_status is current. These values are advisory only and never affect verified.
Parameters
| domain: | integer (required) Numeric ID of domain you would like to retrieve. |
Successful response values
| success: | boolean true |
| domain: |
array Domain Array. |
# Example request
curl https://adstxt.guru/api/1.0/domain/get/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example successful response
{
"success": true,
"domain": {
"id": "1234",
"tag": "abcdefgi01234567",
"name": "domain.com",
"protocol": "https",
"verify_key": "ABCDEFGU01234567",
"verified": "1",
"verify_time": "1780516541",
"verify_version": "1.0.3",
"comment": "1",
"synchronize": "0",
"discovery": "1",
"version_current": "1.0.4",
"version_status": "behind",
"version_match": false
}
}
$api = atg_api('KEY', 'SECRET');
domain/edit
POST
This function allows you to edit a domain under your account.
Parameters
| domain: | integer (required) Numeric ID of domain you would like to edit. |
| protocol: | string https or http. |
| name: | string The new domain name, excluding the protocol. e.g. domain.com |
| comment: | integer 0 if comments should not be included in generated ads.txt file, 1 if comments should be included. |
| synchronize: | integer 1 if automatic synchronization should be enabled (requires 'Connect FTP' or 'Connect WordPress' is configured), 0 if should not be enabled. |
| discovery: | integer 1 if domain should be discoverable using domain tag, 0 if discovery should be disabled. |
Unsuccessful reasons
| invalid: | Invalid name or protocol value. |
| duplicate: | Domain has already been added under this account. |
| conflict: | Domain has already been added under another account. |
Successful response values
| success: | boolean true |
| domain: |
array Domain Array. |
# Example request
curl https://adstxt.guru/api/1.0/domain/edit/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d protocol=http
-d comment=0
# Example successful response
{
"success": true,
"domain": {
"id": "1234",
"tag": "abcdefgi01234567",
"name": "domain.com",
"protocol": "http",
"verify_key": "ABCDEFGU01234567",
"verified": "0",
"comment": "0",
"synchronize": "0",
"discovery": "1"
}
}
$api = atg_api('KEY', 'SECRET');
domain/remove
POST
This function allows you to remove a specific domain under your account.
Parameters
| domain: | integer (required) Numeric ID of domain you would like to remove. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/domain/remove/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
domain/synchronize
POST
This function allows you to provoke synchronization of a specific domain under your account.
This requires 'Connect FTP' or 'Connect WordPress' has been configured, although if neither are configured the API will retrieve the ads.txt file via HTTP to check it against the latest version, if matched then the synchronize is considered successful.
Parameters
| domain: | integer (required) Numeric ID of domain you would like to synchronize. |
Unsuccessful reasons
| error: | A system error has occurred. |
| noftp: | 'Connect FTP' and 'Connect WordPress' have not been configured. |
| connect: | FTP connection failed. |
| upload: | Connection was successful, but FTP upload failed. |
| wordpress: | WordPress connection failed, or the plugin refused the update. See detail below. |
Unsuccessful response values
| detail: | string Always present on an unsuccessful response. A more specific machine-readable code for the failure, or an empty string when there is nothing more specific to report. Read reason first and treat detail as a refinement of it: reason will not change value to describe a new detail, and new detail values may be added over time, so an unrecognised one should be handled as though it were empty. When reason is wordpress, detail carries the reason reported by the ads.txt Guru Connect plugin itself: one of adstxt-unwritable, adstxt-path, adstxt-protected, adstxt-write, adstxt-check, adstxt-invalid, file-mismatch or connect-token. It is empty when the plugin could not be reached at all, or is older than 1.3.0. The first four all mean the file could not be written, most often because the configured path was left behind by a site move; open the ads.txt Guru page in the site's WordPress administration panel, which diagnoses the path and offers to repair it. |
Successful response values
| success: | boolean true |
| method: | string ftp, wordpress, or http will be returned if 'Connect FTP' is not configured but the ads.txt file has already been manually uploaded. |
# Example request
curl https://adstxt.guru/api/1.0/domain/synchronize/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example 'Connect FTP' and 'Connect WordPress' not configured, and HTTP verification failed response
{
"success": false,
"reason": "noftp"
}
# Example WordPress plugin could not write the file response
{
"success": false,
"reason": "wordpress",
"detail": "adstxt-unwritable"
}
# Example FTP synchronize successful response
{
"success": true,
"method": "ftp"
}
# Example HTTP verification successful response
{
"success": true,
"method": "http"
}
$api = atg_api('KEY', 'SECRET');
domain/verify
POST
This function allows you to provoke verification of a specific domain under your account.
Parameters
| domain: | integer (required) Numeric ID of domain you would like to verify. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/domain/verify/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
domain/hosting
POST
This function enables Connect Hosting for a specific domain under your account, returning the hosted ads.txt URL. Direct your domain's /ads.txt path to this URL via 301 redirect and we will serve the latest version of your ads.txt automatically.
The endpoint is idempotent — calling it again for the same domain returns the same token and only updates the enabled flag if changed.
Parameters
| domain: | integer (required) Numeric ID of domain you would like to enable hosting for. |
| enabled: | integer (optional) 1 to enable hosting (default), 0 to disable. |
Unsuccessful reasons
| invalid: | Domain ID is missing, not numeric, or not owned by the authenticated user. |
Successful response values
| success: | boolean true |
| hosting: | array Contains domain, token, enabled, and url. |
# Example request
curl https://adstxt.guru/api/1.0/domain/hosting/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example successful response
{
"success": true,
"hosting": {
"domain": 1234,
"token": "AbCdEfGhIjKlMnOpQrStUvWxYz012345",
"enabled": "1",
"url": "https://adstxt.guru/hosting/AbCdEfGhIjKlMnOpQrStUvWxYz012345/ads.txt"
}
}
# Example disable request
curl https://adstxt.guru/api/1.0/domain/hosting/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d enabled=0
$api = atg_api('KEY', 'SECRET');
domain/wordpress
POST
This function connects a WordPress installation to a specific domain under your account, using the Connect Data generated by the ads.txt Guru WordPress plugin. Once connected, ads.txt updates are pushed to the WordPress site automatically.
The WordPress plugin generates the Connect Data as a base64-encoded string and displays it within the plugin's settings page. Pass this string verbatim to this endpoint.
This endpoint runs the same live handshake against the WordPress URL as the web UI — if the plugin URL cannot be reached or rejects our credentials, the connection is not saved and the response includes a reason.
Parameters
| domain: | integer (required) Numeric ID of the domain to connect. |
| connect_data: | string (required, unless disconnect=1) Base64-encoded Connect Data string from the WordPress plugin. |
| disconnect: | integer (optional) 1 to remove the existing WordPress connection for this domain. |
Unsuccessful reasons
| invalid: | Domain ID is missing/not owned, or connect_data is missing/malformed/fails validation. |
| connect: | Live handshake with the WordPress URL failed (no response or rejected credentials). |
| code-{HTTP_CODE}: | The WordPress URL returned the given HTTP error code (e.g. code-403, code-404). Check the plugin URL is reachable and our IP is not blocked. |
Successful response values
| success: | boolean true |
| wordpress: | array Contains domain, url (when connecting), and connected (boolean). |
# Example connect request
curl https://adstxt.guru/api/1.0/domain/wordpress/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d connect_data=BASE64_BLOB_FROM_PLUGIN
# Example successful response
{
"success": true,
"wordpress": {
"domain": 1234,
"url": "https://example.com",
"connected": true
}
}
# Example disconnect request
curl https://adstxt.guru/api/1.0/domain/wordpress/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d disconnect=1
$api = atg_api('KEY', 'SECRET');
Domain Group
The domain group functions allow you to manage the groups which can collaborate with your domain, you can also request new groups collaborate with your domain using collaborator tags.
These functions do not allow you to manage invitations to collaborate with groups, these are managed with the Domain Invite functions. For clarification, a domain can request collaboration with a group, whereas a group can invite a domain to collaborate.
Group data is provided in what we refer to as the Domain Group Array which includes the group relationship values as outlined below, this should not be confused with the Domain Array or Group Array.
Domain Group Array
| id: | integer Numeric domain ID. |
| group: | string The group name. |
| trust: | boolean/array Returns false if group has not been certified, or an array containing organization and url values if the group is certified & trusted. |
| approved: | integer 1 if collaboration with this group has been approved, 0 if collaboration has not yet been approved. |
# Example domain group array
{
"id": "1234",
"group": "Example Group",
"trust": {
"organization": "Ad Network",
"url": "http://example.com/"
},
"approved": "1"
}
$api = atg_api('KEY', 'SECRET');
domain/group/list
GET or POST
This function allows you to list the groups which are collaborating with this domain.
Parameters
| domain: | integer (required) Numeric ID of domain. |
Successful response values
| success: | boolean true |
| groups: | array An array of Domain Group Arrays, each array record uses the request ID as it's key. |
# Example request
curl https://adstxt.guru/api/1.0/domain/group/list/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example successful response
{
"success": true,
"groups": {
"123": {
"id": "123",
"group": "Example Group",
"trust": {
"organization": "Ad Network",
"url": "http://example.com/"
},
"approved": "1"
},
"124": {
"id": "124",
"group": "Another Group",
"trust": false,
"approved": "0"
}
}
}
$api = atg_api('KEY', 'SECRET');
domain/group/request
POST
This function allows you to request collaboration with a group using their collaborator tag. Requests require approval by the group, except when they have enabled automatic approval.
Collaborator tags are only accessible to the group owner, they must in turn share their collaborator tag with you to enable you to submit a request.
Parameters
| domain: | integer (required) Numeric ID of domain. |
| tag: | string (required) 16 character collaborator tag. |
| message: | string A message to help the group determine your eligibility to collaborate, maximum length is 255 characters, usage of certain characters/symbols is restricted. |
Unsuccessful reasons
| invalid-tag: | Collaborator tag is invalid. |
| invalid-message: | Invalid message, either it exceeds 255 characters or contains restricted characters/symbols. |
| duplicate: | Duplicate request, collaboration with this group already exists or has already been requested. |
| limit: | Maximum publishers limit reached. |
Successful response values
| success: | boolean true |
| request: | array Domain Group Array. |
# Example request
curl https://adstxt.guru/api/1.0/domain/group/request/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d tag=abcdefgi01234567
-d message=My+publisher+account+username+is+ABC123.
# Example invalid tag response
{
"success": false,
"reason": "invalid-tag"
}
# Example successful response
{
"success": true,
"request": {
"id": "123",
"group": "Example Group",
"trust": false,
"approved": "0"
}
}
$api = atg_api('KEY', 'SECRET');
domain/group/remove
POST
This function allows you to remove a group to discontinue collaboration.
Parameters
| domain: | integer (required) Numeric ID of domain. |
| group: | integer (required) Numeric ID of domain group request. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/domain/group/remove/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d group=123
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
Domain Invite
The domain invite functions allow you to view, approve and decline invitations you have received to collaborate with groups.
These functions do not allow you to manage existing group collaboration relationships, these are managed with the Domain Group functions. For clarification, a domain can request collaboration with a group, whereas a group can invite a domain to collaborate.
Invite data is provided in what we refer to as the Domain Invite Array which includes the invite relationship values as outlined below, this should not be confused with the Domain Array or Group Array. The Domain Invite Array follows the same format as the Domain Group Array with the addition of the message value.
Domain Invite Array
| id: | integer Numeric domain ID. |
| group: | string The group name. |
| trust: | boolean/array Returns false if group has not been certified, or an array containing organization and url values if the group is certified & trusted. |
| approved: | integer 1 if collaboration with this group has been approved, 0 if collaboration has not yet been approved. |
| message: | string A message from the group to help you determine the group's eligibility to collaborate. |
# Example domain invite array
{
"id": "1234",
"group": "Example Group",
"trust": {
"organization": "Ad Network",
"url": "http://example.com/"
},
"approved": "1",
"message": "Request from ABC Ad Network as discussed with, john@abcads.com."
}
$api = atg_api('KEY', 'SECRET');
domain/invite/list
GET or POST
This function allows you to list the invitations you have received to collaborate with groups.
Parameters
| domain: | integer (required) Numeric ID of domain. |
Successful response values
| success: | boolean true |
| invites: | array An array of Domain Invite Arrays, each array record uses the invite ID as it's key. |
# Example request
curl https://adstxt.guru/api/1.0/domain/invite/list/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example successful response
{
"success": true,
"invites": {
"123": {
"id": "123",
"group": "Example Group",
"trust": {
"organization": "Ad Network",
"url": "http://example.com/"
},
"approved": "0",
"message": "Request from ABC Ad Network as discussed with, john@abcads.com."
},
"124": {
"id": "124",
"group": "Another Group",
"trust": false,
"approved": "0",
"message": ""
}
}
}
$api = atg_api('KEY', 'SECRET');
domain/invite/approve
POST
This function allows you to approve an invite. Once approved the invite becomes a domain group which can be managed with the Domain Group functions.
Parameters
| domain: | integer (required) Numeric ID of domain. |
| invite: | string (required) Numeric ID of invite. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/domain/invite/approve/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d invite=123
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
domain/invite/decline
POST
This function allows you to decline an invite.
Parameters
| domain: | integer (required) Numeric ID of domain. |
| invite: | string (required) Numeric ID of invite. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/domain/invite/decline/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d invite=123
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
Domain Adstxt
The domain adstxt functions allow you to manage your ads.txt records, for example to add new ads.txt records or to download your ads.txt file.
Adstxt data is provided in what we refer to as the Domain Adstxt Array which includes all your ads.txt records in array format. The Domain Adstxt Array is fundamentally the same as the Group Adstxt array.
Domain Adstxt Array
| version: | version The numeric version number, e.g. 0.0.1. |
| records: | array An array of ads.txt records, as outlined below. Each array record uses the ads.txt record ID as it's key. |
Domain Adstxt Array Records
| tag: | string 16 character tag used with the record ID to identify the record. |
| type: | string data, variable, comment or collaborator. |
| name: | string For data type, the domain name for the record. For variable type, either contact, subdomain or inventorypartnerdomain. For group type, the name of the group. |
| publisher: | string (data type only) Publisher ID. |
| relationship: | string (data type only) DIRECT or RESELLER. |
| certification: | string (data type only) Certification authority ID. |
| value: | string (variable type only) For contact name, the contact details such as an email address or contact form URL. For subdomain name, the related subdomain such as blog.domain.com. For inventorypartnerdomain name, the related domain such as domain.com. |
| comment: | string (comment type only) Comment text. |
| records: | string (collaborator type only) A sub-array of the Domain Adstxt Array Records including all records for the collaborator group. |
# Example domain adstxt array
{
"tag": "abcdefgi01234567",
"type": "data",
"name": "google.com",
"publisher": "pub-0123456",
"relationship": "DIRECT",
"certification": "abcdef012345"
}
$api = atg_api('KEY', 'SECRET');
domain/adstxt/list
GET or POST
This function allows you to retrieve a list of all ads.txt records for a specific domain.
Parameters
| domain: | integer (required) Numeric ID of domain. |
Successful response values
| success: | boolean true |
| adstxt: |
array Domain Adstxt Array. |
# Example request
curl https://adstxt.guru/api/1.0/domain/adstxt/list/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example successful response
{
"success": true,
"adstxt": {
"version": "0.0.1",
"records": {
"123": {
"tag": "abcdefgi01234567",
"type": "data",
"name": "google.com",
"publisher": "pub-0123456",
"relationship": "DIRECT",
"certification": "abcdef012345"
},
"124": {
"tag": "abcdefgi01234568",
"type": "variable",
"name": "contact",
"value": "email@domain.com"
},
"125": {
"tag": "abcdefgi01234569",
"type": "comment",
"comment": "Example comment."
},
"126": {
"tag": "abcdefgi01234560",
"type": "collaborator",
"name": "Example Group",
"records": {
"127": {
"tag": "abcdefgi01234561",
"type": "data",
"name": "google.com",
"publisher": "pub-0123457",
"relationship": "RESELLER",
"certification": "abcdef012345"
}
}
}
}
}
}
$api = atg_api('KEY', 'SECRET');
domain/adstxt/add
POST
This function allows you to add a new ads.txt record.
Parameters
| domain: | integer (required) Numeric ID of domain. |
| type: | string (required) data, variable or comment. |
| name: | string (required for data and variable types) For data type, the domain name for the record. For variable type, either contact, subdomain or inventorypartnerdomain. |
| publisher: | string (required for data type) Publisher ID. |
| relationship: | string (required for data type) DIRECT or RESELLER. |
| certification: | string (data type only) Certification authority ID. |
| value: | string (required for variable type) For contact name, the contact details such as an email address or contact form URL. For subdomain name, the related subdomain such as blog.domain.com. For inventorypartnerdomain name, the related domain such as domain.com. |
| comment: | string (required for comment type) Comment text. |
Unsuccessful reasons
This function may return a reason value, or a reasons array containing multiple reasons.
| error: | A system error has occurred. |
| duplicate: | A duplicate ads.txt record already exists. |
| name-incomplete: | Name value not provided. |
| name-invalid: | Name value is invalid. For a variable record on an app-ads.txt domain this also covers subdomain: the SUBDOMAIN variable is unused in app-ads.txt files and is not accepted there. |
| publisher-incomplete: | Publisher ID not provided. |
| publisher-invalid: | Publisher ID is invalid. |
| relationship-incomplete: | Relationship not provided. |
| relationship-invalid: | Relationship is invalid. |
| certification-invalid: | Certification ID is invalid. |
| value-incomplete: | Value not provided. |
| value-invalid: | Value is invalid. |
| comment-incomplete: | Comment not provided. |
| comment-invalid: | Comment is invalid. |
Successful response values
| success: | boolean true |
| id: | integer Numeric ID for ads.txt record. |
| tag: | string 16 character tag for ads.txt record. |
# Example request
curl https://adstxt.guru/api/1.0/domain/adstxt/add/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d type=data
-d name=google.com
-d publisher=pub-0123456
-d relationship=DIRECT
-d certification=abcdef012345
# Example invalid record response
{
"success": false,
"reasons": [
"name-invalid",
"publisher-invalid"
]
}
# Example successful response
{
"success": true,
"id": "123",
"tag": "abcdefgi01234567"
}
$api = atg_api('KEY', 'SECRET');
domain/adstxt/edit
POST
This function allows you to edit an existing ads.txt record.
Parameters
| domain: | integer (required) Numeric ID of domain. |
| record: | integer (required) Numeric ID of ads.txt record. |
| tag: | string (required) 16 character tag for ads.txt record. |
| type: | string (required) data, variable or comment. |
| name: | string (required for data and variable types) For data type, the domain name for the record. For variable type, either contact, subdomain or inventorypartnerdomain. |
| publisher: | string (required for data type) Publisher ID. |
| relationship: | string (required for data type) DIRECT or RESELLER. |
| certification: | string (data type only) Certification authority ID. |
| value: | string (required for variable type) For contact name, the contact details such as an email address or contact form URL. For subdomain name, the related subdomain such as blog.domain.com. For inventorypartnerdomain name, the related domain such as domain.com. |
| comment: | string (required for comment type) Comment text. |
Unsuccessful reasons
This function may return a reason value, or a reasons array containing multiple reasons.
| id-invalid: | Invalid ads.txt record ID. |
| tag-invalid: | Invalid ads.txt record tag. |
| error: | A system error has occurred. |
| duplicate: | A duplicate ads.txt record already exists. |
| name-incomplete: | Name value not provided. |
| name-invalid: | Name value is invalid. For a variable record on an app-ads.txt domain this also covers subdomain: the SUBDOMAIN variable is unused in app-ads.txt files and is not accepted there. |
| publisher-incomplete: | Publisher ID not provided. |
| publisher-invalid: | Publisher ID is invalid. |
| relationship-incomplete: | Relationship not provided. |
| relationship-invalid: | Relationship is invalid. |
| certification-invalid: | Certification ID is invalid. |
| value-incomplete: | Value not provided. |
| value-invalid: | Value is invalid. |
| comment-incomplete: | Comment not provided. |
| comment-invalid: | Comment is invalid. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/domain/adstxt/edit/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d record=123
-d tag=abcdefgi01234567
-d type=data
-d name=google.com
-d publisher=pub-0123456
-d relationship=DIRECT
-d certification=abcdef012345
# Example invalid record response
{
"success": false,
"reasons": [
"name-invalid",
"publisher-invalid"
]
}
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
domain/adstxt/remove
POST
This function allows you to remove an existing ads.txt record.
Parameters
| domain: | integer (required) Numeric ID of domain. |
| record: | integer (required) Numeric ID of ads.txt record. |
| tag: | string (required) 16 character tag for ads.txt record. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/domain/adstxt/remove/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d record=123
-d tag=abcdefgi01234567
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
domain/adstxt/deduplicate
POST
This function removes duplicate comment lines from a domain's ads.txt, keeping the first occurrence of each. Data records are not affected, and inherited collaborator records are left untouched. The version history is preserved, so the change can be rolled back.
Parameters
| domain: | integer (required) Numeric ID of domain. |
Successful response values
| success: | boolean true |
| removed_count: | integer Number of duplicate comment lines removed (0 if there were none). |
| version: | string The current ads.txt version number after the operation. |
# Example request
curl https://adstxt.guru/api/1.0/domain/adstxt/deduplicate/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example successful response
{
"success": true,
"removed_count": 2,
"version": "1.0.4"
}
$api = atg_api('KEY', 'SECRET');
domain/adstxt/delete_all
POST
This function removes all of a domain's own ads.txt records in a single call. Inherited collaborator group blocks are kept. The version history is preserved, so the change can be rolled back.
Parameters
| domain: | integer (required) Numeric ID of domain. |
Successful response values
| success: | boolean true |
| deleted_count: | integer Number of records removed (0 if the domain had no own records). |
| version: | string The current ads.txt version number after the operation. |
# Example request
curl https://adstxt.guru/api/1.0/domain/adstxt/delete_all/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example successful response
{
"success": true,
"deleted_count": 12,
"version": "1.0.4"
}
$api = atg_api('KEY', 'SECRET');
domain/adstxt/import
POST
This function allows you to import an ads.txt file.
Parameters
| domain: | integer (required) Numeric ID of domain. |
| import: | string (required) The contents of ads.txt file. |
Successful response values
| success: | boolean true |
| added_count: | integer Number of records added. |
| duplicate_count: | integer Number of lines ignored because the record was already present. |
| warning_count: | integer Number of lines which could not be imported, excluding duplicates. |
| warnings: |
array An array of warnings, each array record uses the zero-based index of the submitted line as it's key, and contains msg (the reason), line (the submitted line, HTML encoded) and, on a duplicate only, duplicate. Note this is an empty JSON array ([]) when there are no warnings. |
| retry: | string The lines which were not imported, newline separated, excluding duplicates. Correct them and submit this value again. |
# Example request
curl https://adstxt.guru/api/1.0/domain/adstxt/import/
-d key=KEY
-d secret=SECRET
-d domain=1234
-d import=google.com%2C+pub-0123456%2C+DIRECT%2C+abcdef012345%0A%23+A+Comment%0Acontact%3Demail%40domain.com
# Example successful response
{
"success": true,
"warnings": [],
"warning_count": 0,
"added_count": 3,
"duplicate_count": 0,
"retry": ""
}
# Example successful response, where a line could not be imported
{
"success": true,
"warnings": {
"1": {
"msg": "Duplicate data record ignored.",
"duplicate": true,
"line": "google.com, pub-0123456, DIRECT"
},
"2": {
"msg": "Line not recognised as valid.",
"line": "this is not a record"
}
},
"warning_count": 1,
"added_count": 1,
"duplicate_count": 1,
"retry": "this is not a record"
}
$api = atg_api('KEY', 'SECRET');
domain/adstxt/download
GET or POST
This function allows you to download an ads.txt file.
Parameters
| domain: | integer (required) Numeric ID of domain. |
Successful response values
| success: | boolean true |
| adstxt: | string The content of the ads.txt file. |
# Example request
curl https://adstxt.guru/api/1.0/domain/adstxt/download/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example successful response
{
"success": true,
"adstxt": "# ATG-ABCDEFGU01234567\n# Version 0.0.1\ngoogle.com, pub-0123456, DIRECT, abcdef012345\ncontact=email@domain.com"
}
$api = atg_api('KEY', 'SECRET');
Group
The group functions allow you to manage the groups which would normally be managed under the Collaborate section of your ads.txt Guru account.
These functions give you complete control to add, edit and remove your groups. These functions are only available to users with the 'Ad Network' membership plan, although we currently only allow API access under that plan.
Group data is provided in what we refer to as the Group Array which includes the group values as outlined below.
Group Array
| id: | integer Numeric group ID. |
| tag: | string 16 character group (collaborator) tag. |
| name: | string The group name. |
| trusted: | integer 0 if group is not trusted, 1 if group is not trusted. |
| comment: | integer 0 if comments will not be included in generated ads.txt file, 1 if comments will be included. |
| synchronize: | integer 1 if automatic synchronization is enabled, 0 if not enabled. |
| discovery: | integer 1 if group can be discovered using group (collaborator) tag, 0 if discovery is disabled. |
| approve: | integer 1 if domain requests should be automatically approved, 0 if domain requires require approval. |
| managerdomain: | string The group's manager domain, or an empty string if not set. Emitted as a MANAGERDOMAIN= line on domains the group is applied to in reseller relationship mode. |
# Example group array
{
"id": "1234",
"tag": "abcdefgi01234567",
"name": "Example Group",
"trusted": "0",
"comment": "1",
"synchronize": "0",
"discovery": "1",
"approve": "0",
"managerdomain": "ad-network.example"
}
$api = atg_api('KEY', 'SECRET');
group/list
GET or POST
This function allows you to retrieve a list of all groups under your account.
Successful response values
| success: | boolean true |
| groups: |
array An array of Group Arrays, each array record uses the group ID as it's key. |
# Example request
curl https://adstxt.guru/api/1.0/group/list/
-d key=KEY
-d secret=SECRET
# Example successful response
{
"success": true,
"groups": {
"1234": {
"id": "1234",
"tag": "abcdefgi01234567",
"name": "Example Group",
"trusted": "0",
"comment": "1",
"synchronize": "0",
"discovery": "1",
"approve": "0"
},
"1235": {
"id": "1235",
"tag": "abcdefgi01234568",
"name": "Another Group",
"trusted": "0",
"comment": "1",
"synchronize": "1",
"discovery": "1",
"approve": "1"
}
}
}
$api = atg_api('KEY', 'SECRET');
group/add
POST
This function allows you to add a new group to your account.
Parameters
| name: | string (required) The name of the group. |
Unsuccessful reasons
| invalid: | Invalid name. |
| duplicate: | Group has already been added under this account. |
| conflict: | Group has already been added under another account. |
Successful response values
| success: | boolean true |
| group: |
array Group Array. |
# Example request
curl https://adstxt.guru/api/1.0/group/add/
-d key=KEY
-d secret=SECRET
-d name=Example Group
# Example duplicate domain response
{
"success": false,
"reason": "duplicate"
}
# Example successful response
{
"success": true,
"group": {
"id": "1234",
"tag": "abcdefgi01234567",
"name": "Example Group",
"trusted": "0",
"comment": "1",
"synchronize": "0",
"discovery": "1",
"approve": "0"
}
}
$api = atg_api('KEY', 'SECRET');
group/get
GET or POST
This function allows you to retrieve a specific group under your account.
Parameters
| group: | integer (required) Numeric ID of group you would like to retrieve. |
Successful response values
| success: | boolean true |
| group: |
array Group Array. |
# Example request
curl https://adstxt.guru/api/1.0/group/get/
-d key=KEY
-d secret=SECRET
-d group=1234
# Example successful response
{
"success": true,
"group": {
"id": "1234",
"tag": "abcdefgi01234567",
"name": "Example Group",
"trusted": "0",
"comment": "1",
"synchronize": "0",
"discovery": "1",
"approve": "0"
}
}
$api = atg_api('KEY', 'SECRET');
group/edit
POST
This function allows you to edit a group under your account.
Parameters
| group: | integer (required) Numeric ID of group you would like to edit. |
| name: | string The new group name. |
| comment: | integer 0 if comments should not be included in generated ads.txt file, 1 if comments should be included. |
| synchronize: | integer 1 if automatic synchronization should be enabled, 0 if should not be enabled. |
| discovery: | integer 1 if group should be discoverable using group (collaborator) tag, 0 if discovery should be disabled. |
| approve: | integer 1 if domain requests should be automatically approved, 0 if domain requires require approval. |
| managerdomain: | string Bare domain (e.g. ad-network.example) declared as this group's manager. When the group is applied to a domain in reseller relationship mode, a MANAGERDOMAIN= line pointing to this domain is added automatically. Pass an empty string to clear it. Omit the parameter to leave it unchanged. |
Unsuccessful reasons
| invalid: | Invalid name. |
| invalid-managerdomain: | The supplied manager domain is not a valid domain. |
| duplicate: | Group has already been added under this account. |
| conflict: | Group has already been added under another account. |
Successful response values
| success: | boolean true |
| group: |
array Group Array. |
# Example request
curl https://adstxt.guru/api/1.0/group/edit/
-d key=KEY
-d secret=SECRET
-d group=1234
-d comment=0
-d discovery=0
# Example successful response
{
"success": true,
"group": {
"id": "1234",
"tag": "abcdefgi01234567",
"name": "Example Group",
"trusted": "0",
"comment": "0",
"synchronize": "0",
"discovery": "0",
"approve": "0"
}
}
$api = atg_api('KEY', 'SECRET');
group/remove
POST
This function allows you to remove a specific group under your account.
Parameters
| group: | integer (required) Numeric ID of group you would like to remove. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/group/remove/
-d key=KEY
-d secret=SECRET
-d group=1234
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
group/synchronize
POST
This function allows you to provoke synchronization of a specific group under your account.
Parameters
| group: | integer (required) Numeric ID of group you would like to synchronize. |
Unsuccessful reasons
| error: | A system error has occurred. |
| nosuccess: | No domains were successfully synchronized. |
Unsuccessful response values
| detail: | string Always present on an unsuccessful response, and a refinement of reason in the same way as on domain/synchronize. A group synchronize reports the counts rather than any one domain's cause, so this is currently always an empty string here; synchronize a domain directly to see its own detail. |
| failed_count: | integer The number of domains which failed to be synchronized. |
Successful response values
| success: | boolean true |
| success_count: | integer The number of domains which were successfully synchronized. |
| failed_count: | integer The number of domains which failed to be synchronized. |
# Example request
curl https://adstxt.guru/api/1.0/group/synchronize/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example 'nosuccess' response
{
"success": false,
"reason": "nosuccess",
"failed_count": "5"
}
# Example successful response
{
"success": true,
"success_count": "5",
"failed_count": "0"
}
# Example partially successful response
{
"success": true,
"success_count": "2",
"failed_count": "3"
}
$api = atg_api('KEY', 'SECRET');
Group Domain
The group domain functions allow you to manage which domains the group can collaborate with, you can also invite new domains to a group using domain tags.
These functions do not allow you to manage requests from domains, these are managed with the Group Request functions. For clarification, a domain can request collaboration with a group, whereas a group can invite a domain to collaborate.
Domain data is provided in what we refer to as the Group Domain Array which includes the domain relationship values as outlined below, this should not be confused with the Domain Array or Group Array.
Group Domain Array
| id: | integer Numeric group ID. |
| domain: | string The domain name. |
| flex: | array An array of values for this group's flex records. |
| approved: | integer 1 if collaboration with this domain has been approved, 0 if collaboration has not yet been approved. |
# Example group domain array
{
"id": "1234",
"domain": "domain.com",
"flex": {
"1-abcdefgi01234567": "pub-0123456"
},
"approved": "1"
}
$api = atg_api('KEY', 'SECRET');
group/domain/list
GET or POST
This function allows you to list the domains which are collaborating with this group.
Parameters
| group: | integer (required) Numeric ID of group. |
Successful response values
| success: | boolean true |
| domains: | array An array of Group Domain Arrays, each array record uses the request ID as it's key. |
# Example request
curl https://adstxt.guru/api/1.0/group/domain/list/
-d key=KEY
-d secret=SECRET
-d group=1234
# Example successful response
{
"success": true,
"domains": {
"123": {
"id": "123",
"domain": "domain.com",
"flex": {
"1-abcdefgi01234567": "pub-0123456"
},
"approved": "1"
},
"124": {
"id": "124",
"domain": "example.com",
"flex": {},
"approved": "0"
}
}
}
$api = atg_api('KEY', 'SECRET');
group/domain/invite
POST
This function allows you to invite a domain to collaborate using the domain tag. All requests require approval by the domain.
Domain tags are only accessible to the domain owner, they must in turn share their domain tag with you to enable you to submit an invite.
Parameters
| group: | integer (required) Numeric ID of group. |
| tag: | string (required) 16 character domain tag. |
| message: | string A message to help the domain determine your eligibility to collaborate, maximum length is 255 characters, usage of certain characters/symbols is restricted. |
Unsuccessful reasons
| invalid-tag: | Collaborator tag is invalid. |
| invalid-message: | Invalid message, either it exceeds 255 characters or contains restricted characters/symbols. |
| duplicate: | Duplicate request, collaboration with this domain already exists or has already been requested. |
| limit: | Maximum publishers limit reached. |
Successful response values
| success: | boolean true |
| invite: | array Group Domain Array. |
# Example request
curl https://adstxt.guru/api/1.0/group/domain/invite/
-d key=KEY
-d secret=SECRET
-d group=1234
-d tag=abcdefgi01234567
-d message=Request+from+Ad+Network+as+discussed+with%2C+john%40example.com.
# Example invalid tag response
{
"success": false,
"reason": "invalid-tag"
}
# Example successful response
{
"success": true,
"invite": {
"id": "123",
"domain": "domain.com",
"flex": {},
"approved": "0"
}
}
$api = atg_api('KEY', 'SECRET');
group/domain/edit
POST
This function allows you to edit the flex record publisher ID values for a collaborating domain.
Parameters
| group: | integer (required) Numeric ID of group. |
| domain: | integer (required) Numeric ID of group domain invite. |
| flex-ID-TAG: | string (required) This field must be submitted for each flex record which exists under this group, the ID and TAG values are taken from the Group Adstxt Array. |
Unsuccessful reasons
| ID-TAG: | A separate reason will be returned for any invalid flex record values, the reason will be defined as the ID and TAG as taken from the Group Adstxt Array. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/group/domain/edit/
-d key=KEY
-d secret=SECRET
-d group=1234
-d domain=123
-d flex-1-abcdefgi01234567=pub-0123456
# Example unsuccessful response
{
"success": false,
"reasons": [
"1-abcdefgi01234567"
]
}
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
group/domain/relationship
POST
This function sets how a group's records render on one of its collaborating domains. The change is applied immediately, so the domain's ads.txt reflects it on the next read.
| inherit: | Each record renders exactly as authored on the group (default). |
| direct: | Every data record is forced to DIRECT on this domain. |
| reseller: | Every data record is forced to RESELLER on this domain, and the group's manager domain (if set) is added as a MANAGERDOMAIN= line. |
Parameters
| group: | integer (required) Numeric ID of group. |
| domain: | integer (required) Numeric ID of the domain (as returned by group/domain/list). |
| relationship: | string (required) One of inherit, direct or reseller. |
Unsuccessful reasons
| invalid: | Invalid group, domain, or relationship value. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/group/domain/relationship/
-d key=KEY
-d secret=SECRET
-d group=1234
-d domain=123
-d relationship=reseller
# Example unsuccessful response
{
"success": false,
"reason": "invalid"
}
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
group/domain/remove
POST
This function allows you to remove a domain to discontinue collaboration.
Parameters
| group: | integer (required) Numeric ID of group. |
| domain: | integer (required) Numeric ID of group domain invite. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/group/domain/remove/
-d key=KEY
-d secret=SECRET
-d group=1234
-d domain=123
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
Group Request
The group request functions allow you to view, approve and decline requests you have received to collaborate with domains.
These functions do not allow you to manage existing domain collaboration relationships, these are managed with the Group Domain functions. For clarification, a domain can request collaboration with a group, whereas a group can invite a domain to collaborate.
Request data is provided in what we refer to as the Group Request Array which includes the request relationship values as outlined below, this should not be confused with the Domain Array or Group Array. The Group Request Array follows the same format as the Group Domain Array with the addition of the message value.
Group Request Array
| id: | integer Numeric group ID. |
| domain: | string The domain name. |
| approved: | integer 1 if collaboration with this domain has been approved, 0 if collaboration has not yet been approved. |
| message: | string A message from the domain to help you determine the domain's eligibility to collaborate. |
# Example group request array
{
"id": "1234",
"domain": "domain.com",
"approved": "1",
"message": "My publisher account username is ABC123."
}
$api = atg_api('KEY', 'SECRET');
group/request/list
GET or POST
This function allows you to list the requests you have received to collaborate with domains.
Parameters
| group: | integer (required) Numeric ID of group. |
Successful response values
| success: | boolean true |
| requests: | array An array of Group Request Arrays, each array record uses the request ID as it's key. |
# Example request
curl https://adstxt.guru/api/1.0/group/request/list/
-d key=KEY
-d secret=SECRET
-d domain=1234
# Example successful response
{
"success": true,
"requests": {
"123": {
"id": "123",
"group": "domain.com",
"approved": "0",
"message": "My publisher account username is ABC123."
},
"124": {
"id": "124",
"group": "example.com",
"approved": "0",
"message": ""
}
}
}
$api = atg_api('KEY', 'SECRET');
group/request/approve
POST
This function allows you to approve a request. Once approved the request becomes a group domain which can be managed with the Group Domain functions.
Parameters
| group: | integer (required) Numeric ID of group. |
| request: | string (required) Numeric ID of request. |
Unsuccessful reasons
| limit: | Maximum publishers limit reached. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/group/request/approve/
-d key=KEY
-d secret=SECRET
-d group=1234
-d request=123
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
group/request/decline
POST
This function allows you to decline a request.
Parameters
| group: | integer (required) Numeric ID of group. |
| request: | string (required) Numeric ID of request. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/group/request/decline/
-d key=KEY
-d secret=SECRET
-d group=1234
-d request=123
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
Group Adstxt
The group adstxt functions allow you to manage your ads.txt records, for example to add new ads.txt records or to download your ads.txt file.
Adstxt data is provided in what we refer to as the Group Adstxt Array which includes all your ads.txt records in array format. The Group Adstxt Array is fundamentally the same as the Domain Adstxt array, with the exception that 'collaborator' type records will not be included.
Group Adstxt Array
| version: | version The numeric version number, e.g. 0.0.1. |
| records: | array An array of ads.txt records, as outlined below. Each array record uses the ads.txt record ID as it's key. |
Group Adstxt Array Records
| tag: | string 16 character tag used with the record ID to identify the record. |
| type: | string data, flex, variable or comment. |
| name: | string For data and flex types, the domain name for the record. For variable type, either contact, subdomain or inventorypartnerdomain. For group type, the name of the group. |
| publisher: | string (data type only) Publisher ID. |
| relationship: | string (data and flex types only) DIRECT or RESELLER. |
| certification: | string (data and flex types only) Certification authority ID. |
| value: | string (variable type only) For contact name, the contact details such as an email address or contact form URL. For subdomain name, the related subdomain such as blog.domain.com. For inventorypartnerdomain name, the related domain such as domain.com. |
| comment: | string (comment type only) Comment text. |
# Example group adstxt array
{
"tag": "abcdefgi01234567",
"type": "data",
"name": "google.com",
"publisher": "pub-0123456",
"relationship": "DIRECT",
"certification": "abcdef012345"
}
$api = atg_api('KEY', 'SECRET');
group/adstxt/list
GET or POST
This function allows you to retrieve a list of all ads.txt records for a specific group.
Parameters
| group: | integer (required) Numeric ID of group. |
Successful response values
| success: | boolean true |
| adstxt: |
array Group Adstxt Array. |
# Example request
curl https://adstxt.guru/api/1.0/group/adstxt/list/
-d key=KEY
-d secret=SECRET
-d group=1234
# Example successful response
{
"success": true,
"adstxt": {
"version": "0.0.1",
"records": {
"123": {
"tag": "abcdefgi01234567",
"type": "data",
"name": "google.com",
"publisher": "pub-0123456",
"relationship": "DIRECT",
"certification": "abcdef012345"
},
"124": {
"tag": "abcdefgi01234568",
"type": "variable",
"name": "contact",
"value": "email@domain.com"
},
"125": {
"tag": "abcdefgi01234569",
"type": "comment",
"comment": "Example comment."
}
}
}
}
$api = atg_api('KEY', 'SECRET');
group/adstxt/add
POST
This function allows you to add a new ads.txt record.
Parameters
| group: | integer (required) Numeric ID of group. |
| type: | string (required) data, flex, variable or comment. |
| name: | string (required for data, flex and variable types) For data and flex type, the domain name for the record. For variable type, either contact, subdomain or inventorypartnerdomain. |
| publisher: | string (required for data type) Publisher ID. |
| relationship: | string (required for data and flex types) DIRECT or RESELLER. |
| certification: | string (data and flex types only) Certification authority ID. |
| value: | string (required for variable type) For contact name, the contact details such as an email address or contact form URL. For subdomain name, the related subdomain such as blog.domain.com. For inventorypartnerdomain name, the related domain such as domain.com. |
| comment: | string (required for comment type) Comment text. |
Unsuccessful reasons
This function may return a reason value, or a reasons array containing multiple reasons.
| error: | A system error has occurred. |
| duplicate: | A duplicate ads.txt record already exists. |
| name-incomplete: | Name value not provided. |
| name-invalid: | Name value is invalid. For a variable record on an app-ads.txt domain this also covers subdomain: the SUBDOMAIN variable is unused in app-ads.txt files and is not accepted there. |
| publisher-incomplete: | Publisher ID not provided. |
| publisher-invalid: | Publisher ID is invalid. |
| relationship-incomplete: | Relationship not provided. |
| relationship-invalid: | Relationship is invalid. |
| certification-invalid: | Certification ID is invalid. |
| value-incomplete: | Value not provided. |
| value-invalid: | Value is invalid. |
| comment-incomplete: | Comment not provided. |
| comment-invalid: | Comment is invalid. |
Successful response values
| success: | boolean true |
| id: | integer Numeric ID for ads.txt record. |
| tag: | string 16 character tag for ads.txt record. |
# Example request
curl https://adstxt.guru/api/1.0/group/adstxt/add/
-d key=KEY
-d secret=SECRET
-d group=1234
-d type=data
-d name=google.com
-d publisher=pub-0123456
-d relationship=DIRECT
-d certification=abcdef012345
# Example invalid record response
{
"success": false,
"reasons": [
"name-invalid",
"publisher-invalid"
]
}
# Example successful response
{
"success": true,
"id": "123",
"tag": "abcdefgi01234567"
}
$api = atg_api('KEY', 'SECRET');
group/adstxt/edit
POST
This function allows you to edit an existing ads.txt record.
Parameters
| group: | integer (required) Numeric ID of group. |
| record: | integer (required) Numeric ID of ads.txt record. |
| tag: | string (required) 16 character tag for ads.txt record. |
| type: | string (required) data, flex, variable or comment. |
| name: | string (required for data, flex and variable types) For data and flex type, the domain name for the record. For variable type, either contact, subdomain or inventorypartnerdomain. |
| publisher: | string (required for data type) Publisher ID. |
| relationship: | string (required for data and flex type) DIRECT or RESELLER. |
| certification: | string (data and flex type only) Certification authority ID. |
| value: | string (required for variable type) For contact name, the contact details such as an email address or contact form URL. For subdomain name, the related subdomain such as blog.domain.com. For inventorypartnerdomain name, the related domain such as domain.com. |
| comment: | string (required for comment type) Comment text. |
Unsuccessful reasons
This function may return a reason value, or a reasons array containing multiple reasons.
| id-invalid: | Invalid ads.txt record ID. |
| tag-invalid: | Invalid ads.txt record tag. |
| error: | A system error has occurred. |
| duplicate: | A duplicate ads.txt record already exists. |
| name-incomplete: | Name value not provided. |
| name-invalid: | Name value is invalid. For a variable record on an app-ads.txt domain this also covers subdomain: the SUBDOMAIN variable is unused in app-ads.txt files and is not accepted there. |
| publisher-incomplete: | Publisher ID not provided. |
| publisher-invalid: | Publisher ID is invalid. |
| relationship-incomplete: | Relationship not provided. |
| relationship-invalid: | Relationship is invalid. |
| certification-invalid: | Certification ID is invalid. |
| value-incomplete: | Value not provided. |
| value-invalid: | Value is invalid. |
| comment-incomplete: | Comment not provided. |
| comment-invalid: | Comment is invalid. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/group/adstxt/edit/
-d key=KEY
-d secret=SECRET
-d group=1234
-d record=123
-d tag=abcdefgi01234567
-d type=data
-d name=google.com
-d publisher=pub-0123456
-d relationship=DIRECT
-d certification=abcdef012345
# Example invalid record response
{
"success": false,
"reasons": [
"name-invalid",
"publisher-invalid"
]
}
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
group/adstxt/remove
POST
This function allows you to remove an existing ads.txt record.
Parameters
| group: | integer (required) Numeric ID of group. |
| record: | integer (required) Numeric ID of ads.txt record. |
| tag: | string (required) 16 character tag for ads.txt record. |
Successful response values
| success: | boolean true |
# Example request
curl https://adstxt.guru/api/1.0/group/adstxt/remove/
-d key=KEY
-d secret=SECRET
-d group=1234
-d record=123
-d tag=abcdefgi01234567
# Example successful response
{
"success": true
}
$api = atg_api('KEY', 'SECRET');
group/adstxt/import
POST
This function allows you to import an ads.txt file.
Parameters
| group: | integer (required) Numeric ID of group. |
| import: | string (required) The contents of ads.txt file. |
Successful response values
| success: | boolean true |
| added_count: | integer Number of records added. |
| duplicate_count: | integer Number of lines ignored because the record was already present. |
| warning_count: | integer Number of lines which could not be imported, excluding duplicates. |
| warnings: |
array An array of warnings, each array record uses the zero-based index of the submitted line as it's key, and contains msg (the reason), line (the submitted line, HTML encoded) and, on a duplicate only, duplicate. Note this is an empty JSON array ([]) when there are no warnings. |
| retry: | string The lines which were not imported, newline separated, excluding duplicates. Correct them and submit this value again. |
# Example request
curl https://adstxt.guru/api/1.0/group/adstxt/import/
-d key=KEY
-d secret=SECRET
-d group=1234
-d import=google.com%2C+pub-0123456%2C+DIRECT%2C+abcdef012345%0A%23+A+Comment%0Acontact%3Demail%40domain.com
# Example successful response
{
"success": true,
"warnings": [],
"warning_count": 0,
"added_count": 3,
"duplicate_count": 0,
"retry": ""
}
$api = atg_api('KEY', 'SECRET');
group/adstxt/download
GET or POST
This function allows you to download an ads.txt file.
Parameters
| group: | integer (required) Numeric ID of group. |
Successful response values
| success: | boolean true |
| adstxt: | string The content of the ads.txt file. |
# Example request
curl https://adstxt.guru/api/1.0/group/adstxt/download/
-d key=KEY
-d secret=SECRET
-d group=1234
# Example successful response
{
"success": true,
"adstxt": "# ATG-ABCDEFGU01234567\n# Version 0.0.1\ngoogle.com, pub-0123456, DIRECT, abcdef012345\ncontact=email@domain.com"
}
$api = atg_api('KEY', 'SECRET');
Validate
The validate functions allow you to validate ads.txt files programmatically, either by providing the URL of an ads.txt file, or by providing the contents of an ads.txt file directly.
These functions are metered. Each call is charged against your token balance, and a call your balance will not cover is refused with a 402 before anything runs. See Paying for Calls for what each call costs. A subscription that includes API access covers them instead and is never charged against a balance.
Validation results for each line of the ads.txt file are provided in what we refer to as the Adstxt Validation Array which includes the values as outlined below.
validate/sellersjson checks the other file in the chain: the sellers.json an SSP, exchange or ad network publishes to say who each seller_id in its system is. Its results are a list of findings, each naming the IAB Tech Lab error code where one exists, described on its own entry.
Adstxt Validation Array
| line: | integer ads.txt file line number. |
| type: | string The line type, either data, variable, comment, blank, invalid or unknown. |
| variable: | string (variable type only) contact, subdomain or inventorypartnerdomain. |
| duplicate: | array An array containing line numbers of matching duplicate records. |
| data: | string The contents of the line. |
| error: | array An array containing error reasons as outlined below. Errors are considered serious failures which must be resolved. |
| warning: | array An array containing warning reasons as outlined below. Warnings are points of concern which should be checked. |
| notice: | array An array containing notice reasons as outlined below. Notices highlight ways to improve the ads.txt formatting. |
| valid: | interger 1 if the record is valid, or 0 if the record has at least one error, warning or notice. |
Error reasons
| line-invalid: | Line is invalid and failed all validation. |
| data-format: | Data record is formatted incorrectly (less than 3 or more than 4 parts). |
| data-domain-invalid: | Data record domain is invalid. |
| data-publisher-invalid: | Data record publisher ID is invalid. |
| data-relationship-invalid: | Data record relationship value is invalid. |
| data-certification-invalid: | Data record certification ID cannot be an identifier (empty, over 64 characters, or containing something other than letters, numbers, dots, hyphens and underscores). |
| data-certification-incorrect: | Data record certification ID is incorrect. |
Warning reasons
| data-domain-invalid: | Data record domain may be invalid. |
| data-certification-not-tagid: | Data record certification ID is not a TAG-ID (16 hexadecimal characters). The specification sets no format for this field, so this is a warning and not an error. |
| variable-name-invalid: | Variable name is invalid, must be 'CONTACT', 'SUBDOMAIN', 'INVENTORYPARTNERDOMAIN', 'OWNERDOMAIN' or 'MANAGERDOMAIN'. |
| variable-contact-invalid: | Variable contact value is invalid. |
| variable-subdomain-invalid | Variable subdomain value is invalid. |
| variable-inventorypartnerdomain-invalid | Variable inventorypartnerdomain value is invalid. |
| variable-subdomain-unused | The subdomain variable is unused in app-ads.txt files and will be ignored. Only returned when the file being validated is an app-ads.txt, which is known from a 'url' request. |
Notice reasons
| line-inline-comment: | Line contains inline comment. |
| line-whitespace: | Line contains unnecessary whitespace. |
| data-domain-case: | Data record domain value contains uppercase characters. |
| data-domain-whitespace: | Data record domain value contains unnecessary whitespace. |
| data-publisher-whitespace: | Data record publisher ID contains unnecessary whitespace. |
| data-relationship-case: | Data record relationship value contains lowercase characters. |
| data-relationship-whitespace: | Data record relationship value contains unnecessary whitespace. |
| data-certification-whitespace: | Data record certification ID value contains unnecessary whitespace. |
| comment-compatibility: | Comment contains unusual characters/symbols, consider removing for compatibility. |
| variable-inventorypartnerdomain-adstxt: | Inventory partner domains are followed to the partner's ads.txt file, not their app-ads.txt file. Only returned when the file being validated is an app-ads.txt, which is known from a 'url' request. |
App-ads.txt Location Array
An app-ads.txt file is not read from the host you publish it on. A verifier takes the developer URL from your app store listing and derives a host from it, dropping labels on the way, so a file published on www.example.com is read by nobody: the app-ads.txt specification states that verifiers read example.com/app-ads.txt instead. Where the file you validated by url is an app-ads.txt, the response carries an appads array describing where a verifier will look for it.
| host: | string The host of the URL you provided. |
| canonical: | string The host a verifier reads the file from first. |
| parent: | string or false The host a verifier falls back to when no file is found on canonical, or false where there is no distinct parent. |
| suffix: | string The public suffix matched in the host, e.g. co.uk. |
| suffix_known: | boolean false where that suffix is not in our Public Suffix List snapshot, in which case the rest is our best reading of the host rather than a certainty. |
| crawl_order: | array Every app-ads.txt URL a verifier tries, in the order it tries them: both schemes on canonical, then both on parent. |
| advice: | array An array of code / level / message arrays, as outlined below. Empty where the URL you provided is exactly where a verifier reads the file. |
Location advice codes
| appads-host-not-crawled: | warning - no verifier reads app-ads.txt from the host you provided, so records published there are not seen at all. Publish at canonical. |
| appads-parent-fallback: | notice - the file on canonical replaces the one on parent rather than adding to it, because the parent is read only when no file is found on the subdomain. |
| appads-suffix-unknown: | notice - the public suffix in the host is not in our snapshot of the Public Suffix List. |
Note the location advice is not counted in warning_count or notice_count: those totals are sums over the individual lines of the file, and this advice is about the file as a whole.
# Example adstxt validation array
{
"line": 1,
"type": "data",
"duplicate": [
"4",
"17"
],
"data": "domaincom , 1234567, DIREC, abcdefghijk",
"error": [
"data-domain-invalid",
"data-relationship-invalid"
],
"warning": [
"data-certification-not-tagid"
],
"notice": [
"data-domain-whitespace"
],
"valid": "0"
}
# Example app-ads.txt location array
# (url=https://www.example.com/app-ads.txt)
{
"host": "www.example.com",
"canonical": "example.com",
"parent": false,
"suffix": "com",
"suffix_known": true,
"crawl_order": [
"https://example.com/app-ads.txt",
"http://example.com/app-ads.txt"
],
"advice": [
{
"code": "appads-host-not-crawled",
"level": "warning",
"message": "Verifiers will not read app-ads.txt from www.example.com. ..."
}
]
}
$api = atg_api('KEY', 'SECRET');
validate/adstxt
POST
This function allows you to validate a raw ads.txt file, either by providing the URL of an ads.txt file, or by providing the contents of an ads.txt file directly.
This function is metered. The call is charged against your token balance, and a call your balance will not cover is refused with a 402 before anything runs. See Paying for Calls for what it costs. A subscription that includes API access covers it instead and is never charged against a balance.
Parameters
| data: | string The contents of an ads.txt file, up to 1 MB. |
| url: | string (recommended method) The full URL of an ads.txt file, e.g. http://domain.com/ads.txt A URL ending in app-ads.txt is validated as an app-ads.txt file and adds an App-ads.txt Location Array to the response. |
Unsuccessful reasons
| error: | A system error has occurred. |
| empty-file: | The ads.txt file is empty or contains only whitespace. |
| toolarge: | ads.txt file is greater the 1 MB, the maximum size supported. |
| url-invalid: | An invalid URL was provided. |
| url-connect: | Connection to URL failed. |
Successful response values
Note, the ads.txt file is considered valid if the error_count value is zero.
| success: | boolean true |
| error_count: | integer The total number of errors detected. |
| warning_count: | integer The total number of warnings detected. |
| notice_count: | integer The total number of notices detected. |
| valid_count: | integer The total number of valid lines detected. |
| appads: | array (app-ads.txt url only) An App-ads.txt Location Array describing where a verifier will read the file from. Returned when the url you provided names an app-ads.txt file and a location can be derived from its host, and also returned alongside an unsuccessful url-connect reason, where it is often the explanation. |
| adstxt: | array An array of Adstxt Validation Arrays, each array record uses the line number as it's key. |
# Example request
curl https://adstxt.guru/api/1.0/validate/adstxt/
-d key=KEY
-d secret=SECRET
-d url=http://domain.com/ads.txt
# Example successful response
{
"success": true,
"error_count": 1,
"warning_count": 0,
"notice_count": 1,
"valid_count": 0,
"adstxt": {
"1": {
"line": 1,
"type": "data",
"duplicate": [],
"data": "example.com, abcdefg, DIRECT",
"error": [],
"warning": [],
"notice": [],
"valid": "1"
},
"2": {
"line": 2,
"type": "unknown",
"duplicate": [],
"data": " test",
"error": [
"line-invalid"
],
"warning": [],
"notice": [
"line-whitespace"
],
"valid": "0"
}
}
}
$api = atg_api('KEY', 'SECRET');
validate/sellersjson
POST
This function checks a sellers.json file, the file an SSP, exchange or ad network publishes to say who each seller_id in its system belongs to. Give it the advertising system's domain and it reads /sellers.json from there the way a buyer's crawler does, following the specification's redirect rules, or give it the contents of the file. It is the same check as the free sellers.json Validator, so the two always agree about a file.
This function is metered. The call is charged against your token balance, and a call your balance will not cover is refused with a 402 before anything runs. See Paying for Calls for what it costs. A subscription that includes API access covers it instead and is never charged against a balance. It shares the rate limits of validate/adstxt.
Parameters
| data: | string The contents of a sellers.json file, up to 1 MB. |
| url: | string (recommended method) The domain of the advertising system, e.g. example.com, the first field of an ads.txt line: we read https://example.com/sellers.json, and http once if https does not answer. A full URL is read as given, so a file can be checked before it moves into place. Files up to 5 MB are read. |
Unsuccessful reasons
| error: | A system error has occurred. |
| empty-file: | The sellers.json you sent in data is empty or contains only whitespace. Nothing was charged. |
| toolarge: | The sellers.json you sent in data is larger than 1 MB. For a larger file, send its domain as url instead. |
| url-invalid: | The url is not something we will read, such as an IP address rather than a domain. message says why. Nothing was fetched and nothing was charged. |
| url-connect: | The file could not be read. message says what happened, iab carries the IAB code where one applies (10010 for a status other than 2xx, 10030 for a file that does not arrive within 20 seconds, 10040 for more than five redirects within the domain, 10050 for a second redirect after the file was delegated), and fetch shows every request made. |
Successful response values
The answer is a list of findings, errors first, then warnings, then notices. A finding is one kind of problem, however many sellers it applies to: it says how many in count and lists the first ten in examples, so the three counts count findings, not sellers.
| success: | boolean true |
| outcome: | string The worst level found: error, warning, notice, or clean where there is nothing. invalid where the text is not JSON at all. |
| error_count: | integer The number of findings that are errors. |
| warning_count: | integer The number of findings that are warnings. |
| notice_count: | integer The number of findings that are notices. |
| fetch: | array (url only) url (what we read first), final_url (what answered, after any redirects), http_code, content_type (an empty string where the server sent none), seconds, and chain: every request made, in order, each a url and its HTTP code. |
| parsed: | boolean false where the text is not JSON. |
| summary: | array bytes, version, sellers, types (sellers of each seller_type), confidential, passthrough, domains (distinct seller domains), contact_email, contact_address and identifiers (their names). |
| findings: | array An array of Sellers.json Finding Arrays. |
| syntax: | array or false Where the text is not JSON and the parser could say where: line, column, message, and up to 40 characters before and after that point. false otherwise. |
Sellers.json Finding Array
Build on a finding's key, level and iab. Its title and detail are written for people and may be reworded.
| key: | string What kind of problem this is, one of the keys below. |
| level: | string error, warning or notice. Errors are what the specification requires and buyers' crawlers report; warnings are valid by the letter of it but cause trouble in practice; notices need no change. |
| iab: | string The IAB Tech Lab error code, or an empty string where the Tech Lab defines none. A duplicated seller_id carries both of its codes, as 12060 / 13060. |
| title: | string A one-line description. |
| detail: | string What the problem means and how to fix it. |
| count: | integer The number of sellers it applies to, or 1 for a problem with the file as a whole. |
| examples: | array Up to ten of the places it occurs, in file order, each with position (counting from 1), seller_id, value (the offending value written as JSON, cut to 120 characters) and suggestion (what it most likely should be, or an empty string). For seller-id-duplicate, each example is the repeat and its value the position of the entry it repeats. |
Finding keys
content-type |
error | 20020 | Served with no Content-Type, or one other than application/json |
https-unavailable |
warning | Read over http, because https did not answer (a bare domain only) | |
delegated |
notice | 10050 | Redirected once to another root domain, which the specification allows |
not-at-root |
warning | 10010 | Not at _/sellers.json_ at the root of the domain, where buyers read it |
bom |
warning | Starts with a byte order mark | |
json |
error | 22010 | Not JSON: empty, saved as UTF-16, or a syntax error, which syntax locates |
parent |
error | 21020 | The top level is not an object |
version |
error or warning | 21020 | No version, or not "1.0"; a warning where it is the number 1.0 |
sellers |
error or warning | 21020 | No sellers list, or not a list; a warning, with no code, where the list is empty |
contact-email |
notice or warning | No contact_email (a notice), or not an email address (a warning) | |
contact-address |
warning | contact_address is not a string | |
identifiers |
warning | identifiers is not a list, or an entry is not a name and value pair | |
ext |
warning | The top level's ext is not an object | |
parent-keys |
notice | The top level carries names the specification does not define | |
seller-not-object |
error | 21030 | An entry in sellers is not an object |
seller-id-missing |
error | 21030 | A seller has no seller_id |
seller-id-empty |
error | 21030 | A seller_id is empty |
seller-id-type |
error | 21030 | A seller_id is not a string |
seller-id-number |
warning | A seller_id is a number, which loses leading zeros and precision | |
seller-id-whitespace |
warning | A seller_id has spaces around it, so no ads.txt line matches it | |
seller-id-duplicate |
error | 12060 / 13060 | A seller_id is listed more than once; each example is the repeat, and its value the position of the entry it repeats |
seller-type-missing |
error | 21030 | A seller has no seller_type |
seller-type-invalid |
error | 21050 | A seller_type is not PUBLISHER, INTERMEDIARY or BOTH |
seller-type-case |
notice | A seller_type is not in capitals | |
is-confidential |
error | 21060 | is_confidential is not 0 or 1 |
is-passthrough |
error | 21070 | is_passthrough is not 0 or 1 |
name-missing |
error | A seller that is not confidential has no name | |
name-type |
error | A name is not a string | |
confidential-named |
warning | A confidential seller is named anyway | |
domain-missing |
warning | 21040 | A seller that is not confidential has no domain |
domain-type |
error | 21010 | A domain is not a string |
domain-invalid |
error | 21010 | A domain is not a valid domain name |
domain-url |
error | 21010 | A domain is a URL; the example's suggestion is the root domain |
domain-not-root |
error | 21010 | A domain is not a root domain; the example's suggestion is the root |
domain-whitespace |
warning | 21010 | A domain has spaces around it |
domain-suffix |
warning | 21010 | A domain ends in a suffix the Public Suffix List does not know |
comment-type |
warning | A comment is not a string | |
seller-ext |
warning | A seller's ext is not an object | |
seller-keys |
notice | Sellers carry names the specification does not define |
The codes are those of the IAB Tech Lab's published Supply Chain error code overview. IAB and IAB Tech Lab are trademarks of the Interactive Advertising Bureau, and ads.txt Guru is not affiliated with or endorsed by IAB Tech Lab.
# Example request
curl https://adstxt.guru/api/1.0/validate/sellersjson/
-d key=KEY
-d secret=SECRET
-d url=ssp.example.com
# Example successful response
{
"success": true,
"outcome": "error",
"error_count": 1,
"warning_count": 0,
"notice_count": 0,
"fetch": {
"url": "https://ssp.example.com/sellers.json",
"final_url": "https://ssp.example.com/sellers.json",
"http_code": 200,
"content_type": "application/json",
"seconds": 0.38,
"chain": [
{
"url": "https://ssp.example.com/sellers.json",
"code": 200
}
]
},
"parsed": true,
"summary": {
"bytes": 482,
"version": "1.0",
"sellers": 2,
"types": {
"PUBLISHER": 2,
"INTERMEDIARY": 0,
"BOTH": 0
},
"confidential": 0,
"passthrough": 0,
"domains": 2,
"contact_email": "adops@ssp.example.com",
"contact_address": false,
"identifiers": []
},
"findings": [
{
"key": "domain-url",
"level": "error",
"iab": "21010",
"title": "A \"domain\" is a URL, not a domain",
"detail": "The spec asks for the root domain alone, ...",
"count": 1,
"examples": [
{
"position": 2,
"seller_id": "pub-2",
"value": "\"https://www.example.com/\"",
"suggestion": "example.com"
}
]
}
],
"syntax": false
}
# Example unsuccessful response
{
"success": false,
"reason": "url-connect",
"message": "https://ssp.example.com/sellers.json returned HTTP 404 rather than the file. A sellers.json must be served with a 2xx status.",
"iab": "10010",
"fetch": {
"url": "https://ssp.example.com/sellers.json",
"final_url": "https://ssp.example.com/sellers.json",
"http_code": 404,
"content_type": "text/html",
"seconds": 0.21,
"chain": [
{
"url": "https://ssp.example.com/sellers.json",
"code": 404
}
]
}
}
$api = atg_api('KEY', 'SECRET');
Compare
The compare functions allow you to verify whether specific ads.txt records are included in the ads.txt files of multiple domains. This functionality can be used to ensure your publishers have implemented specific ads.txt records.
These functions are metered. Every domain in your list is charged against your token balance, and a call your balance will not cover is refused with a 402 before anything runs. See Paying for Calls for what each call costs. A subscription that includes API access covers them instead and is never charged against a balance.
A single call carries at most 100 domains, the same limit for every caller regardless of plan or balance. Over it nothing is fetched and nothing is charged: the call is refused with a domains-limit reason, and that response states the limit and the number of domains you sent. Split a longer list across several calls; there is no limit on how many calls make up a job.
Comparison results are provided for each domain which is provided in what we refer to as the Adstxt Comparison Array which includes the values as outlined below.
Adstxt Comparison Array
| domain: | string The domain name which was provided. |
| id: | string The ID for the domain (if provided). |
| url: | string The URL which was checked - this is the domain name, including the protocol used and the filename that was read ('ads.txt', or 'app-ads.txt' where the domains entry asked for it). |
| status: | string success, missing or failed. |
| missing: | array An array containing all missing records. |
| error: | string An error message, if applicable. |
| reason: | string A detailed explanation for the error message, if applicable. |
| fetched_at: | integer (only where the file was read) The unix timestamp at which we actually read this domain's file. Absent for a domain we never managed to read, because there is no read to report. |
| age: | integer (only where the file was read) Seconds between that read and this response. 0 means we fetched the file for this call. Anything higher means we answered from a copy we already held: we keep a publisher's file for a short time, and honour that publisher's own Cache-Control or Expires where they set one, so a repeated question does not send their server a repeated request. The response always says which you got, so a client that needs a live read can check this field. |
# Example adstxt comparison array
{
"domain": "example.com",
"id": "CUSTOM-ID",
"url": "http://example.com/ads.txt",
"status": "missing",
"missing": [
"domain.com, 123456, DIRECT"
],
"error": "",
"reason": "",
"fetched_at": 1789856084,
"age": 0
}
$api = atg_api('KEY', 'SECRET');
compare/adstxt
POST
This function allows you to verify whether specific ads.txt records are included in the ads.txt files of multiple domains.
This function is metered. Every domain in your list is charged against your token balance, and a call your balance will not cover is refused with a 402 before anything runs. See Paying for Calls for what it costs. A subscription that includes API access covers it instead and is never charged against a balance.
A single call carries at most 100 domains, the same limit for every caller regardless of plan or balance. Over it nothing is fetched and nothing is charged: the call is refused with a domains-limit reason whose response states the cap as limit and what you sent as domains. Split a longer list across several calls; there is no limit on how many calls make up a job.
Parameters
| adstxt: | string (required) The ads.txt records which you would like to check are present on the specified domains, formatted as a standard ads.txt file. Only data records will be compared - variables and comments will be ignored. |
| domains: | string (required) A list of domains to check. Each domain can include a protocol (http or https); if not included then https is used. The file is always read from the root of the domain, so any directories in a path are ignored - but ending an entry with 'app-ads.txt' checks that domain's app-ads.txt file instead of its ads.txt. A unique ID can be included after each domain separated by a comma - this ID is then returned in the results to assist with processing. |
Unsuccessful reasons
| adstxt-toolarge: | ads.txt input must be less than 1 MB. |
| adstxt-error: | Unable to process ads.txt input. |
| domains-toolarge: | Domains input must be less than 1 MB. |
| domains-error: | Unable to process domains input. |
| domains-limit: | Domains input carries more than the 100 domains allowed in one call. The response states the cap as limit and the number you sent as domains. Nothing was fetched and nothing was charged. |
Successful response values
| success: | boolean true |
| matched_count: | integer The total number of domains which matched all records. |
| partial_count: | integer The total number of domains which were missing some or all records. |
| failed_count: | integer The total number of domains with errors such as connection errors or non-existent ads.txt files. |
| results: | array An array of Adstxt Comparison Arrays for each domain being checked. |
| tokens_charged: | integer (metered calls only) Tokens this call actually took, after any domain we did not fetch was credited back. See Paying for Calls. |
| tokens_not_charged: | integer (metered calls only) Domains in your list we did not fetch, and so did not charge for. Each one carries a reason in its result saying why. |
# Example request
curl https://adstxt.guru/api/1.0/compare/adstxt/
-d key=KEY
-d secret=SECRET
-d adstxt=domain.com, 12345, DIRECT
-d domains=example.com,EXAMPLE-ID\n
http://www.missing.com\n
subdomain.failed.com
# Example successful response
{
"success": true,
"matched_count": 1,
"partial_count": 1,
"failed_count": 1,
"results": [
{
"domain": "example.com",
"id": "EXAMPLE-ID",
"url": "https://example.com/ads.txt",
"status": "success",
"missing": [],
"error": "",
"reason": "",
"fetched_at": 1789856084,
"age": 0
},
{
"domain": "http://missing.com",
"id": "ID",
"url": "https://www.missing.com/ads.txt",
"status": "missing",
"missing": [
"domain.com, 12345, DIRECT"
],
"error": "",
"reason": "",
"fetched_at": 1789854284,
"age": 1800
},
{
"domain": "subdomain.failed.com",
"id": "",
"url": "https://subdomain.failed.com/ads.txt",
"status": "failed",
"missing": [],
"error": "Connection error",
"reason": "Your URL returned a 404 File Not Found error indicating an ads.txt file can not be found."
}
]
}
$api = atg_api('KEY', 'SECRET');