Get Cheap Games Outbound API

The outbound API from Get Cheap Games — 9 operation(s) for outbound.

GitHub OpenAPI

Operations 9

GET /api/out/game/{slug} Outbound Game #
GET /api/out/play/{slug} Outbound Play #
GET /api/badge/{slug}.svg Price Badge #
GET /api/out/{offer_id} Outbound Interstitial #
GET /api/out/{offer_id}/go Outbound #
GET /api/out/promo/{slug} Promo Interstitial #
GET /api/out/promo/{slug}/go Outbound Promo #
GET /api/out/store/{code} Outbound Store #
GET /api/out/partner/ig Outbound Instant Gaming #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • 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.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/getcheapgames-com:getcheapgames-com-outbound-api"
All apis
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.

Get an API 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 Specification

getcheapgames-com-outbound-api-openapi.yml Raw ↑
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