Agilis API Documentation
The Agilis REST API lets advertisers manage offers programmatically. All requests are made over
HTTPS to https://ads.agilis.dating and authenticated with your API key, supplied in
the x-api-key request header. Responses are returned as JSON.
Developer Guide
The Agilis Advertising API lets developers create and manage advertiser offers programmatically. A typical integration starts by fetching available categories, estimating the price of an offer, creating the offer, then verifying and managing it through the offer management endpoints.
1 Fetch categories using
GET /categories2 Estimate price using
POST /offers/price-estimate3 Create the offer using
POST /offers4 Verify the offer using
GET /offers?environment=live or GET /offers?environment=test5 Manage the offer using pause, resume, analytics, or delete endpoints
Payment methods
When creating an offer, use payment_method=E to generate a Stripe Checkout payment URL. The offer remains in Awaiting Payment status until Stripe confirms payment. After payment, the offer becomes Active if the start date is now or in the past, or Scheduled if the start date is in the future.
Use payment_method=B to pay from the organisation's Ad Unit balance. In this case, Ad Units are deducted immediately and no Stripe payment URL is returned.
Authentication
All requests require a valid API key in the x-api-key request header. API keys are managed in the Agilis Ad Portal under Manage API Keys. Invalid, disabled, or expired keys return 401 {"message": "Unauthorised"}.
Environment testing
Use environment=TEST when creating test offers. Test offers are only returned by GET /offers?environment=test and do not appear to real Agilis users. Use environment=LIVE for live campaigns.
Implementation notes
POST /offers is currently not idempotent. Developers should avoid blind retries on create requests because retrying after a timeout or network error may create duplicate offers. Idempotency support will be added in a future version.
Pagination and filtering are currently not supported for GET /offers. The endpoint returns the offers for the requested environment in a single response. Pagination and filtering support is planned for a future version.
Rate-limit headers may be returned by API responses, including successful and error responses: X-RateLimit-Limit shows the total requests allowed in the current window, and X-RateLimit-Remaining shows the requests remaining in the current window.
Category List
The Category List API returns all active categories available to the organisation that owns the API key. It is typically called before creating an offer, because offer creation requires a valid category ID returned by this endpoint.
Header: x-api-key: your_api_key_here
Method: GET
category_id integer
Unique ID of the category.
Example: 1
category_name string
Name of the category.
Example: "Retail"
200 — Categories retrieved successfully.
401 — Invalid API key or disabled account.
500 — Internal server error.
import requests
url = "https://ads.agilis.dating/categories"
headers = {"x-api-key": "your_api_key_here"}
response = requests.get(url, headers=headers)
print(response.json()){
"categories": [
{ "category_id": 1, "category_name": "Retail" },
{ "category_id": 2, "category_name": "Food & Beverage" }
]
}
Create Offer
Creates a new offer for the authenticated advertiser. The request is sent as
multipart/form-data with the offer image supplied as a binary file stream.
The image is checked by automated content moderation before the offer is created.
Header: x-api-key: your_api_key_here
Content-Type: multipart/form-data
category_id integer, required
A valid category ID from the Category List API.
Example: 1
title string, required
Example: "20% off summer sale"
description string, required
Example: "Discount valid through July"
terms_and_conditions string, required
Maximum 500 characters.
Example: "Valid online only."
url string, required
Example: "https://advertiseroffer.com"
image binary, required
JPG, PNG or GIF, maximum 10MB, sent as a binary file stream.
Recommended size: 1080x1080px
currency string, required
One of GBP, USD, CAD, AUD (case-insensitive).
location[] array, required
Latitude and longitude as two values.
Example: [51.5074, -0.1278]
radius integer, required
Radius in miles, minimum 5.
Example: 10
start_datetime string, required
ISO 8601, UTC.
Example: "2026-07-10T08:00:00Z"
expiry_datetime string, required
ISO 8601, UTC.
Example: "2026-07-12T20:30:00Z"
payment_method string, required
E = Stripe payment link by email; B = deduct from organisation balance.
environment string, required
One of TEST or LIVE (case-insensitive).
S1 — Offer created (payment link issued, or Live/Scheduled if paid from balance).
E1 — One or more inputs are missing or invalid (including unsupported currency).
E2 — The uploaded image was rejected by content moderation.
E3 — Insufficient Ad Unit balance.
import requests
url = "https://ads.agilis.dating/offers"
headers = {"x-api-key": "your_api_key_here"}
files = {
"image": ("offer.jpg", open("/path/to/offer.jpg", "rb"), "image/jpeg")
}
data = {
"category_id": 1,
"title": "20% off summer sale",
"description": "Discount valid through July",
"terms_and_conditions": "Valid online only.",
"url": "https://advertiseroffer.com",
"currency": "GBP",
"location[]": [51.5074, -0.1278],
"radius": 10,
"start_datetime": "2026-07-10T08:00:00Z",
"expiry_datetime": "2026-07-12T20:30:00Z",
"payment_method": "E",
"environment": "LIVE"
}
response = requests.post(url, headers=headers, files=files, data=data)
print(response.json()){
"return_code": "S1",
"offer_id": 45,
"status": "Awaiting Payment",
"payment_url": "https://checkout.stripe.com/c/pay/cs_test_..."
}
View Offers
Returns all offers created by the authenticated advertiser for the requested environment. Offers whose image was rejected by content moderation are never created, so they are not returned.
Header: x-api-key: your_api_key_here
Method: GET
environment string, required
One of test or live
(case-insensitive).
Example: /offers?environment=test
Each offer object contains: offer_id, title, category,
description, terms_and_conditions, url,
image (signed CloudFront URL), latitude, longitude,
radius, gender (array such as ["Male","Female"], or
null), start_datetime, expiry_datetime,
creation_datetime and offer_status
(Active, Paused, Ended or Awaiting Payment).
200 — Offers returned (count is 0 with an empty array if none exist).
401 — Invalid API key or disabled account.
500 — Internal server error.
import requests
url = "https://ads.agilis.dating/offers"
headers = {"x-api-key": "your_api_key_here"}
params = {"environment": "test"}
response = requests.get(url, headers=headers, params=params)
print(response.json()){
"count": 1,
"offers": [
{
"offer_id": 45,
"title": "20% off summer sale",
"category": "Retail",
"description": "Discount valid through July",
"terms_and_conditions": "Valid online only.",
"url": "https://advertiseroffer.com",
"image": "https://ads.agilis.dating/92/offers/45/offer_orig.png",
"latitude": 51.5074,
"longitude": -0.1278,
"radius": 10,
"gender": ["Male", "Female"],
"start_datetime": "2026-07-10T08:00:00Z",
"expiry_datetime": "2026-07-12T20:30:00Z",
"creation_datetime": "2026-06-01T10:00:00Z",
"offer_status": "Active"
}
]
}
Pause and Resume Offer
Pauses a running offer or resumes a paused offer. These are two separate endpoints. The offer must belong to the account that owns the API key.
Header: x-api-key: your_api_key_here
Method: POST
offer_id integer, required
Path parameter.
Example: 45
S1 — Offer paused successfully.
S2 — Offer resumed successfully.
E2 — Offer has already ended.
E3 — Offer is already paused (pause request).
E4 — Offer is already running (resume request).
E5 — Offer is awaiting payment.
import requests
headers = {"x-api-key": "your_api_key_here"}
# Pause an offer
pause = requests.post(
"https://ads.agilis.dating/offers/45/pause", headers=headers)
print(pause.json())
# Resume an offer
resume = requests.post(
"https://ads.agilis.dating/offers/45/resume", headers=headers)
print(resume.json()){
"return_code": "S1",
"message": "Offer has been paused."
}
Delete Offer
Deletes an offer belonging to the authenticated account. If the offer is awaiting payment, its Stripe payment link is disabled before deletion.
Header: x-api-key: your_api_key_here
Method: DELETE
offer_id integer, required
Path parameter.
Example: 45
S1 — Offer deleted successfully.
E1 — Invalid input, or the offer does not belong to this account.
import requests
url = "https://ads.agilis.dating/offers/45"
headers = {"x-api-key": "your_api_key_here"}
response = requests.delete(url, headers=headers)
print(response.json()){
"return_code": "S1",
"message": "Offer has been deleted."
}
View Offer Analytics
Returns view and click metrics for a specific offer over the requested time interval. The offer must belong to the account that owns the API key.
Header: x-api-key: your_api_key_here
Method: GET
offer_id integer, required
Path parameter.
Example: 45
interval string, required
One of 24h, 7d, 30d, 60d, 90d or all.
200 — Analytics returned successfully.
401 — Invalid API key, disabled account, or offer not owned by this account.
500 — Internal server error.
import requests
url = "https://ads.agilis.dating/offers/45/analytics"
headers = {"x-api-key": "your_api_key_here"}
params = {"interval": "30d"}
response = requests.get(url, headers=headers, params=params)
print(response.json()){
"offer_id": 45,
"interval": "30d",
"start_datetime": "2026-07-10T08:00:00Z",
"end_datetime": "2026-08-09T08:00:00Z",
"status": "Active",
"metrics": {
"views": 4789,
"clicks": 1032
}
}
Offer Price Estimate
Calculates the price of an offer in Ad Units before it is created, based on the duration and the number of Agilis users within the target radius.
Header: x-api-key: your_api_key_here
Content-Type: application/json
Method: POST
start_datetime string, required
ISO 8601, UTC.
Example: "2026-07-10T08:00:00Z"
end_datetime string, required
ISO 8601, UTC.
Example: "2026-07-12T20:30:00Z"
location array, required
Latitude and longitude.
Example: [51.5074, -0.1278]
radius integer, required
Miles, minimum 5, maximum 30.
Example: 10
S1 — Estimate calculated successfully.
E1 — One or more inputs are missing or invalid.
E2 — A date/time is not in valid ISO 8601 format.
import requests
url = "https://ads.agilis.dating/offers/price-estimate"
headers = {"x-api-key": "your_api_key_here"}
payload = {
"start_datetime": "2026-07-10T08:00:00Z",
"end_datetime": "2026-07-12T20:30:00Z",
"location": [51.5074, -0.1278],
"radius": 10
}
response = requests.post(url, headers=headers, json=payload)
print(response.json()){
"return_code": "S1",
"price_estimate": 45.50
}