Get Cheap Games Outbound API
The outbound API from Get Cheap Games — 9 operation(s) for outbound.
The outbound API from Get Cheap Games — 9 operation(s) for outbound.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/getcheapgames-com:getcheapgames-com-outbound-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: getcheapgames Outbound API
description: Game key price comparison. All money is integer cents; rankings are on the price each store lists, without the service fee a marketplace adds at checkout.
version: 0.1.0
tags:
- name: outbound
paths:
/api/out/game/{slug}:
get:
tags:
- outbound
summary: Outbound Game
description: 'A buy link that does not go stale: a game, optionally a store, and a market.
For links that leave this site and live on somewhere else — an AI
assistant''s answer, a chat, a saved note — and are clicked days later. An
offer''s own `/api/out/{id}` names one listing, and a listing can be
re-regioned or withdrawn; this names what the reader wanted and resolves it
when they click: the lead of the market pick (`market_pick.pick`, at
`store` when given), the in-stock key that activates in `country` that the
page''s title, answer and Product markup quote. Then it goes through the
same interstitial and `/go` as every other click, so the affiliate tag and
the click record are exactly the ones a click on the page produces.
`offer` is the listing the page led with when the link was written (the
crawler shell and the app put it on their lead link). While it is still in
the pick — in stock, activating here, in the pick''s currency, at `store`
when one is named — the reader goes to that very offer, even if another
has since become a cent cheaper: they are buying what they were shown.
Once it is not, the comparison is redone and they go to today''s lead.
An id is never trusted further than that, so a guessed or edited one can
only ever reach an offer the page would quote anyway.
`currency` is the page''s currency when the reader chose another than the
market''s (the app''s switcher): the pick is redone in it, as the page''s
was, so `offer=` is found. Without it, the market''s own.
A free game is not sold here at all: whatever is listed under its name is
a currency pack or an account, not the game, so the link goes to the
game''s page, as it does when no key that activates in `country` is in
stock. An unknown game goes to the market''s home page.'
operationId: outbound_game_api_out_game__slug__get
parameters:
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: store
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 32
- type: 'null'
title: Store
- name: country
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 8
- type: 'null'
title: Country
- name: offer
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 24
- type: 'null'
title: Offer
- name: currency
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 8
- type: 'null'
title: Currency
- name: src
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 48
- type: 'null'
title: Src
responses:
'307':
description: Successful Response
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/out/play/{slug}:
get:
tags:
- outbound
summary: Outbound Play
description: 'A free game''s partner "Play" link (`FreeToPlayPin.play_url`: Admitad''s
War Thunder, Enlisted, World of Tanks and GOG demo links), through here.
The pages linked the partner straight away, in the app''s buttons and in
the crawler shell, so every crawler, link checker and prefetch that
followed one was a click on the network''s side: Admitad counted 3,913
clicks for 12-18 Oct 2026 where our own records had 12 store clicks and
28 plays by people. Under /api/out/ the link is disallowed in robots.txt,
a prefetch is refused, and only a person is sent on (`_robot`): anything else lands
on the game''s page here, and the network never sees it.'
operationId: outbound_play_api_out_play__slug__get
parameters:
- name: slug
in: path
required: true
schema:
type: string
title: Slug
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/badge/{slug}.svg:
get:
tags:
- outbound
summary: Price Badge
description: 'A game''s cheapest price as an image, for other sites to embed.
The site''s backlinks: a blog, a stream overlay or a forum post shows it
linked to the game''s page here (the snippet is on every product page), and
the price stays true because it is drawn when fetched — the cheapest key
that activates in `country`, the same offer `/api/out/game/…` sends a buyer
to. Only text we escaped goes in, and an `` runs no script besides.
In the market''s language (`lang=` overrides it, any of the site''s 25) and
money as that market writes it. "−X% vs Steam" only where Steam sells the
game in that currency for more. `theme=dark|light`, `size=sm|md`. An
unknown game or one with no key to sell draws a neutral "Compare key
prices" badge, never a made-up price, rather than a broken image on
somebody else''s page.'
operationId: price_badge_api_badge__slug__svg_get
parameters:
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: country
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 8
- type: 'null'
title: Country
- name: lang
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 8
- type: 'null'
title: Lang
- name: theme
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 8
- type: 'null'
title: Theme
- name: size
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 4
- type: 'null'
title: Size
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/out/{offer_id}:
get:
tags:
- outbound
summary: Outbound Interstitial
description: 'The branded page a buyer sees on the way to a store.
It deliberately does NOT log the click and does NOT know the destination.
Both belong to `/go` below, and splitting them is what makes the page safe
to show:
* The tagged URL stays server-side. Putting it in this document would undo
the reason the redirect exists at all — `build_affiliate_url` runs on the
server so the affiliate id is never somewhere it can be read off the page
or stripped by an extension.
* A click means a buyer who actually left. Anything that merely FETCHES
this page — a crawler, a link preview, a browser prefetching on hover —
gets HTML and stops there. Under the old single-endpoint design every one
of those wrote an `outbound_clicks` row indistinguishable from a sale.
Set `GCG_INTERSTITIAL_DELAY_MS=0` to bypass it entirely and go straight to
the store. This sits between a buyer and a purchase, so it needs a kill
switch that does not require a deploy.'
operationId: outbound_interstitial_api_out__offer_id__get
parameters:
- name: offer_id
in: path
required: true
schema:
type: integer
title: Offer Id
- name: src
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 48
- type: 'null'
title: Src
- name: e
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 96
- type: 'null'
title: E
responses:
'200':
description: Successful Response
content:
text/html:
schema:
type: string
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/out/{offer_id}/go:
get:
tags:
- outbound
summary: Outbound
description: 'Redirect to a store, tagged with our affiliate identity.
Server-side for three reasons: the affiliate id never reaches the browser,
the click is logged even when an extension would have blocked a beacon, and
the ids can be rotated without shipping a new frontend.
302, not 301 — the destination changes whenever the affiliate id or the
store''s product URL does, and a permanent redirect would be cached past
that.
`c` is the click id the interstitial minted (`_go_url`): the same page
reaching here twice is one row, and the network sees one sub-id. A
prefetch is refused before anything is written (`is_prefetch`).'
operationId: outbound_api_out__offer_id__go_get
parameters:
- name: offer_id
in: path
required: true
schema:
type: integer
title: Offer Id
- name: c
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 64
- type: 'null'
title: C
- name: src
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 48
- type: 'null'
title: Src
- name: r
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 64
- type: 'null'
title: R
- name: e
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 96
- type: 'null'
title: E
responses:
'307':
description: Successful Response
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/out/promo/{slug}:
get:
tags:
- outbound
summary: Promo Interstitial
description: 'The coupon handed over on the way out of a banner.
A banner used to be a bare 302, and the code it applies to sat in a strip
on the home page — which meant the page gave away the one thing worth
clicking for before anybody clicked. The code now lives here, on the way
out, where it is worth something to both sides.
This half does NOT redirect and does NOT know the destination, exactly as
the offer interstitial does not: `/go` owns both. That split is what keeps
the tracked URL server-side, and it is why a crawler or a link preview that
merely FETCHES this page gets HTML and stops there.
Falls straight through to the redirect when there is no live code for the
store. A scratch card over an empty promise is worse than no scratch card,
and it would put a page between a reader and a shop for nothing.'
operationId: promo_interstitial_api_out_promo__slug__get
parameters:
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: src
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 48
- type: 'null'
title: Src
- name: e
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 96
- type: 'null'
title: E
responses:
'200':
description: Successful Response
content:
text/html:
schema:
type: string
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/out/promo/{slug}/go:
get:
tags:
- outbound
summary: Outbound Promo
description: 'A banner''s own destination, kept off the page.
The creative''s tracked URL carries our publisher hash, so it lives in
settings for the same three reasons every other affiliate id does: it never
reaches the browser, an extension cannot strip it, and rotating it does not
need a frontend build.
Falls back to the store''s front page when the destination is unconfigured.
A banner that lands one level too high still earns; one that 404s does not,
and an empty setting must not take the home page down with it.'
operationId: outbound_promo_api_out_promo__slug__go_get
parameters:
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: c
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 64
- type: 'null'
title: C
- name: src
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 48
- type: 'null'
title: Src
- name: e
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 96
- type: 'null'
title: E
responses:
'307':
description: Successful Response
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/out/store/{code}:
get:
tags:
- outbound
summary: Outbound Store
description: 'Redirect to a store''s own front page, tagged where we can tag it.
The footer lists every store we compare, and those names are now links —
a reader who wants to look at Gamivo directly should not have to retype it.
Routing them through here rather than linking the domain straight keeps the
affiliate id server-side, exactly as the per-offer redirect does, and means
a programme we activate later starts earning without a frontend change.
No interstitial: that page exists to explain a PRICE we are handing off,
and there is no price here. The click IS recorded, as placement ''store''
with no offer, game or price (migration 0063): these are tagged affiliate
exits, and leaving them out meant the networks always counted more than
the dashboard did — the audit found one in two days of logs, against six
counted clicks.
302 rather than 301 for the same reason as the offer redirect: the tagged
destination changes whenever the affiliate id does.
Two ways to tag, and which one applies is a property of the programme.
`tag_url` handles the stores whose own URL takes a parameter — G2A''s
`gtag`. A NETWORK programme cannot work that way: the tracked link is the
network''s, and the shop''s url goes inside it. Kinguin runs on Admitad, so
its front-page link is a configured gotolink rather than anything derived
from `store.domain`.
That value is a setting and NOT an `affiliate_wrap` on the store row, which
is the obvious-looking fix and would break the site — see the comment on
`store_url_kinguin`. A wrap applies to every url for the store, and Kinguin
offer urls come from the feed already tagged.'
operationId: outbound_store_api_out_store__code__get
parameters:
- name: code
in: path
required: true
schema:
type: string
title: Code
- name: src
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 48
- type: 'null'
title: Src
- name: e
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 96
- type: 'null'
title: E
responses:
'307':
description: Successful Response
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/out/partner/ig:
get:
tags:
- outbound
summary: Outbound Instant Gaming
description: 'The Instant Gaming banner''s hop, routed through us like every other.
Three path segments, like `/out/promo/...` and `/out/store/...`, and not
the tidier `/out/ig`: that is two segments and would be matched by
`/out/{offer_id}` above, which is declared first and types the id as an
int — so the tidier spelling is a 422 on every click. Depending on
declaration order instead would work until somebody reorders the file.
Their widget builds its own anchor in the browser, pointing straight at
their site — so unlike every other advert here the click never touched our
origin, and nothing we measure could see it. The frontend rewrites that
anchor to this endpoint and hands the destination along.
The destination is carried rather than configured because the creative
rotates: it was advertising FC 27 when this was written, and sending that
click to the front page instead of the page the picture promised is the
kind of tidy-looking change that quietly costs conversions.
Two things are enforced rather than trusted. The host must be theirs, or
this is an open redirect wearing our domain. And the partner id is
OVERWRITTEN with ours, so a hand-edited link cannot point our traffic at
somebody else''s account — which is the one thing a caller could otherwise
change to their benefit and our cost.
Recorded like every other exit, as placement ''partner'' with no store row
(Instant Gaming is not a store we compare), tagged when our partner id
went on.'
operationId: outbound_instant_gaming_api_out_partner_ig_get
parameters:
- name: to
in: query
required: false
schema:
type: string
default: ''
title: To
- name: src
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 48
- type: 'null'
title: Src
- name: e
in: query
required: false
schema:
anyOf:
- type: string
maxLength: 96
- type: 'null'
title: E
responses:
'307':
description: Successful Response
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
components:
schemas:
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
ValidationError:
properties:
loc:
items:
anyOf:
- type: string
- type: integer
type: array
title: Location
msg:
type: string
title: Message
type:
type: string
title: Error Type
input:
title: Input
ctx:
type: object
title: Context
type: object
required:
- loc
- msg
- type
title: ValidationError