Neon Commerce Storefront API
The Storefront API from Neon Commerce — 9 operation(s) for storefront.
The Storefront API from Neon Commerce — 9 operation(s) for storefront.
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/neon-commerce-storefront-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
openapi: 3.2.0
info:
title: Storefront API
description: Every call involved with setting up a storefront is listed in the Storefront API. Every call requires an API key. Each key is scoped to a storefront and can only update the models associated with that storefront.
version: 1.0.0
servers:
- url: https://api.neonpay.com
security:
- EnvironmentApiKey: []
tags:
- name: Storefront
paths:
/storefront/items:
post:
summary: Create items
operationId: createStorefrontItems
description: 'Create items. Read more about inventory setup [here](https://neonpay.readme.io/docs/offers).
If any operation fails, the error is returned and all changes are reverted.
'
requestBody:
required: true
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Item'
responses:
'201':
description: Empty.
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
/storefront/offer-groups:
post:
summary: Create an offer group
description: 'Offer groups are used to group offers in the storefront. Read more about inventory setup [here](https://neonpay.readme.io/docs/offers).
This operation takes a list of offer groups and adds them to your existing offer groups. If any operation fails, all changes are reverted and the error is returned.
'
operationId: createStorefrontOfferGroups
requestBody:
required: true
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/OfferGroup'
responses:
'201':
description: Empty.
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
/storefront/offers:
post:
summary: Create offers
operationId: createStorefrontOffers
description: 'An offer is the resource that players purchase on the storefront. Read more about inventory setup [here](https://neonpay.readme.io/docs/offers).
This operation takes a list of offer objects and adds them to your existing offers. If any operation fails, all changes are reverted and the error is returned.
'
requestBody:
required: true
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Offer'
responses:
'201':
description: Empty.
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
get:
summary: Get offers
operationId: getStorefrontOffers
description: Get a paginated list of offers.
parameters:
- in: query
allowReserved: true
name: limit
required: false
schema:
type: integer
default: 20
minimum: 1
maximum: 100
- in: query
allowReserved: true
name: startingAfter
required: false
schema:
type: string
description: 'A cursor for use in pagination. An offer SKU that defines your place in the list of offers. It''ll fetch the next page of the list.
'
- in: query
allowReserved: true
name: endingBefore
required: false
schema:
type: string
description: 'A cursor for use in pagination. An offer SKU that defines your place in the list of offers. It''ll fetch the previous page of the list.
'
responses:
'200':
description: Offers retrieved successfully
content:
application/json:
schema:
type: object
required:
- data
- links
properties:
data:
type: array
items:
$ref: '#/components/schemas/Offer'
links:
type: object
required:
- previous
- next
properties:
previous:
type:
- string
- 'null'
description: 'Link to paginate to the previous page of the list. If null, there is no previous page.
'
next:
type:
- string
- 'null'
description: 'Link to paginate to the next page of the list. If null, there is no next page.
'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
/storefront/item/{code}:
delete:
summary: Delete an item
operationId: deleteStorefrontItem
description: Delete an item by its code.
parameters:
- in: path
name: code
required: true
schema:
type: string
example: gem
responses:
'200':
description: Empty.
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
get:
summary: Get an item by code
operationId: getStorefrontItem
description: Get an item by its code.
parameters:
- in: path
name: code
required: true
schema:
type: string
example: gem
responses:
'200':
description: Item retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Item'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
put:
summary: Update an item by code
operationId: updateStorefrontItem
description: Update an item. This replaces the existing item with the input data.
parameters:
- in: path
name: code
required: true
schema:
type: string
example: gem
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Item'
responses:
'201':
description: Empty.
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
/storefront/offer/{sku}:
delete:
summary: Delete an offer
operationId: deleteStorefrontOffer
description: Delete an offer by its SKU.
parameters:
- in: path
name: sku
required: true
schema:
type: string
example: 500_GEMS
responses:
'200':
description: Empty.
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
'409':
$ref: '#/components/responses/Conflict'
tags:
- Storefront
get:
summary: Get an offer by SKU
operationId: getStorefrontOffer
description: Get an offer by its SKU.
parameters:
- in: path
name: sku
required: true
schema:
type: string
example: 500_GEMS
responses:
'200':
description: Offer retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Offer'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
put:
summary: Update an offer by SKU
operationId: updateStorefrontOffer
description: Update an offer. This replaces the existing offer with the input data.
parameters:
- in: path
name: sku
required: true
schema:
type: string
example: 500_GEMS
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Offer'
responses:
'200':
description: Empty.
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
/storefront/offer-group/{code}:
delete:
summary: Delete an offer group
operationId: deleteStorefrontOfferGroup
description: Delete an offer by its code.
parameters:
- in: path
name: code
required: true
schema:
type: string
example: promoted
responses:
'200':
description: Empty.
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
get:
summary: Get an offer group by code
operationId: getStorefrontOfferGroup
description: Get an offer group by its code.
parameters:
- in: path
name: code
required: true
schema:
type: string
example: promoted
responses:
'200':
description: Offer group retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/OfferGroup'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
put:
summary: Update an offer group by code
operationId: updateStorefrontOfferGroup
description: Update an offer group. This replaces the existing offer group with the input data.
parameters:
- in: path
name: code
required: true
schema:
type: string
example: promoted
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OfferGroup'
responses:
'201':
description: Empty.
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
/storefront/prices:
get:
summary: Get localized pricing by IP address.
operationId: getRegionalPricingByIpAddress
security:
- ClientKey: []
parameters:
- in: query
allowReserved: true
name: ip
required: true
description: The IP address of the user
schema:
type: string
responses:
'200':
description: IP address parsed successfully
content:
application/json:
schema:
type: object
required:
- isSupported
- isFallback
properties:
isSupported:
type: boolean
description: True if this IP can be served prices (either locally or via Global Store fallback), false otherwise
isFallback:
type: boolean
description: True when prices are served via Global Store fallback (USD) because the country is env-disabled or globally unsupported. Always false when `isSupported` is false or when prices are served locally.
prices:
type: object
description: Map of offer SKU to localized price
additionalProperties: true
country:
type: string
description: The country used for pricing (may be "US" if Global Store fallback is applied)
currency:
type: string
description: The currency of the included prices
'400':
$ref: '#/components/responses/BadRequest'
'401':
description: Invalid API key.
content:
application/json:
schema:
$ref: '#/components/schemas/APIError'
tags:
- Storefront
/storefront/theme:
get:
summary: Get a storefront theme
description: Get a storefront theme
operationId: getTheme
responses:
'201':
$ref: '#/components/responses/Theme'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
put:
summary: Update the theme for a storefront
description: Programatically update the configuration for a theme
operationId: updateTheme
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Theme'
responses:
'200':
description: Empty
content:
application/json:
schema:
type: object
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/InvalidApiKey'
tags:
- Storefront
/storefront/callbacks:
post:
summary: Register a URL to handle events throughout the storefront and checkout flow.
description: Learn more about callbacks [here](https://neonpay.readme.io/docs/webhooks-and-callbacks).
operationId: subscribeToCallbacks
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- url
properties:
url:
description: The destination URL for these callbacks
type: string
format: uri
example: https://gameUrl.com/account.getInventory
secret:
description: A shared secret used to sign every callback. If not provided, Neon will generate a secret.
type: string
enabledEvents:
description: The set of API calls this URL will handle
type: array
default:
- account.getInventory
items:
type: string
enum:
- account.getInventory
eventVersion:
description: The version of schema to be used for calls to this URL
default: 1
type: number
hooksToExpire:
description: 'Any callback IDs to expire.
Only one URL can be registered to listen to events for a specific callback. If you register a new
URL, you''ll need to expire the old URLs first. You can do so by passing their IDs here.
'
type: array
items:
type: string
description: Callback ID to expire
responses:
'201':
description: Callback registered successfully
content:
application/json:
schema:
type: object
required:
- secret
- ids
properties:
secret:
type: string
description: The secret used to sign this callback's data, either passed in or generated by Neon
ids:
type: array
description: The created callback IDs
items:
type: string
description: The UUID of the created callback
'400':
$ref: '#/components/responses/BadRequest'
'401':
description: Invalid API key.
content:
application/json:
schema:
$ref: '#/components/schemas/APIError'
callbacks:
account.getInventory:
'{$request.body#/url}':
post:
security: []
parameters:
- $ref: '#/components/parameters/NeonSignature'
- in: header
name: X-Neon-Webhook-Type
required: true
schema:
type: string
description: The type of this request (`account.getInventory`).
requestBody:
content:
application/json:
schema:
type: object
description: Request body for event version 1
properties:
data:
type: object
description: User-supplied data used to look up an account
required:
- account
properties:
account:
type: string
description: The user's unique account ID
responses:
'200':
description: The account's purchase limits
content:
application/json:
schema:
$ref: '#/components/schemas/PlayerInventory'
'401':
description: No account matching the provided data could be found; Neon will not retry these requests
account.validate:
'{$request.body#/url}':
post:
security: []
parameters:
- $ref: '#/components/parameters/NeonSignature'
- in: header
name: X-Neon-Webhook-Type
required: true
schema:
type: string
description: The type of this request (`account.validate`).
requestBody:
content:
application/json:
schema:
type: object
description: Request body for event version 1
properties:
data:
type: object
description: User-supplied data used to look up an account
required:
- accountId
properties:
accountId:
type: string
maxLength: 1000
description: The user's unique account ID
responses:
'200':
description: Additional information about the user's account
content:
application/json:
schema:
type: object
required:
- isValid
properties:
isValid:
type: boolean
description: Whether or not this account ID corresponds to a valid account.
accountId:
type:
- string
- 'null'
description: The corrected or normalized account ID, if available. If provided, this will be used instead of the input account ID for fulfillment.
displayName:
type:
- string
- 'null'
description: 'The display name for the player. This will be used instead of the `accountId` for display if provided. This can be used when the player ID is not meant to be player-facing. Some common examples are a custom gamertag (e.g. "GreatGamer123"), the player''s name (e.g. "John Smith"), or an email address (e.g. "johnsmith@gmail.com").
'
metadata:
type: object
description: 'Additional metadata that you''d like to track alongside events for this user. This data will be included in analytics events and webhooks. It should not include any sensitive or internal data like internal authentication tokens. Common use cases are analytics session IDs or device IDs.
'
additionalProperties: true
'401':
description: No account matching the provided data could be found; Neon will not retry these requests
tags:
- Storefront
components:
responses:
Conflict:
description: The request conflicts with the current state of the resource
content:
application/json:
schema:
$ref: '#/components/schemas/APIError'
BadRequest:
description: An error response from an invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/APIError'
InvalidApiKey:
description: An error response from an invalid API key
content:
application/json:
schema:
$ref: '#/components/schemas/APIError'
Theme:
description: The theme for a storefront
content:
application/json:
schema:
$ref: '#/components/schemas/Theme'
schemas:
PlayerInventory:
type: array
items:
type: object
required:
- sku
- purchased
properties:
sku:
type: string
description: The offer SKU
purchased:
type: number
minimum: 0
description: The amount of this offer the user has already purchased
limit:
type:
- number
- 'null'
minimum: 0
description: The total number of this offer the user may purchase. If null, there is no limit. If zero, the limit is 0
startTime:
anyOf:
- type:
- string
- 'null'
description: The time from which this restriction should be made effective, if applicable, expressed as an ISO 8601 string
- type:
- number
- 'null'
description: The time from which this restriction should be made effective, if applicable, expressed in milliseconds since the start of the epoch
durationInSeconds:
type:
- number
- 'null'
minimum: 0
description: The number of seconds after `startTime` for which this restriction should be effective. If not passed, the restriction is indefinitely effective
Offer:
type: object
required:
- sku
- priceTierCode
- isTargetedOffer
- shouldPreviewTargetedOffer
- shouldHideOfferWhenClaimed
- groups
- imageFileName
- backgroundImageFileName
- items
- text
properties:
sku:
type: string
description: The unique SKU for this item. This SKU is used for API operations, and to identify the offer during fulfillment.
priceTierCode:
description: The price tier code for this item. Read more about price tiers [here](https://neonpay.readme.io/docs/pricing).
type: string
isTargetedOffer:
description: Whether the item should only be displayed based on player-specific information (e.g. reaching a certain in-game level).
type: boolean
default: false
shouldPreviewTargetedOffer:
description: Whether the targeted offer should be displayed if it is not yet unlocked. Only used if `isTargetedOffer` is set to `true`.
type: boolean
default: false
shouldHideOfferWhenClaimed:
description: Flag to indicate whether the offer should be hidden once it has been claimed.
type: boolean
example: true
default: false
isHidden:
description: Flag to indicate whether the offer should be hidden from the storefront.
type: boolean
example: false
default: false
containsRandomizedContent:
description: Flag to indicate whether this offer contains randomized content (e.g., loot boxes). Used for jurisdiction-based restrictions.
type: boolean
example: false
default: false
buttonLayout:
type:
- string
- 'null'
enum:
- null
- ADD_TO_CART
- BUY_NOW
- ADD_TO_CART_AND_BUY_NOW
description: Controls which purchase button(s) are shown on the offer card. Null defaults to add-to-cart behaviour.
limit:
description: Number to be used if the offer should be limited to a certain number or purchases per user.
type:
- integer
- 'null'
timeLimits:
type: array
items:
type: object
description: Time limits to be set for this offer, if the offer is time-limited.
required:
- previewDate
- startDate
- endDate
properties:
previewDate:
description: The time (in UTC) at which the item will first be visible on the storefront.
type:
- string
- 'null'
format: date-time
example: '2023-06-23T20:00:00.000Z'
startDate:
description: The time (in UTC) at which the item will first be available for purchase.
type:
- string
- 'null'
format: date-time
example: '2023-06-23T20:00:00.000Z'
endDate:
description: The time (in UTC) at which the item will no longer be available for purchase.
type:
- string
- 'null'
format: date-time
example: '2023-06-23T20:00:00.000Z'
groups:
type: array
description: Offer group configuration for this offer. Offer groups can be created by calling `POST /storefront/offer-groups`, and must be created prior to calling this endpoint.
items:
type: object
required:
- code
- order
- style
properties:
code:
type: string
description: The group's code. This is the value of `code` you passed when calling `POST /storefront/groups`.
order:
type: number
description: The priority of this offer within its group. Lower values show up earlier.
style:
description: How this item should be rendered. Promoted items are displayed more prominently in their group.
type: string
default: default
imageFileName:
description: The file name of this offer's image. This is the value of `fileName` you passed in when calling `POST /assets/inventory-images`.
type:
- string
- 'null'
example: gem-24x24.png
backgroundImageFileName:
description: The file name of this offer's background image. This is the value of `fileName` you passed in when calling `POST /assets/inventory-images`.
type:
- string
- 'null'
example: gem-background.png
items:
type: array
description: The items included in this offer. Items can be created by calling `POST /storefront/items`, and must be created prior to calling this endpoint.
items:
type: object
required:
- code
- quantity
- text
properties:
code:
type: string
description: The item's code. This is the value of `code` you passed when calling `POST /storefront/items`.
quantity:
type: number
description: The number of this item to be included in this offer.
originalQuantity:
type:
- number
- 'null'
description: The number of this item to be included in this offer excluding any bonus amounts (i.e. `originalQuantity = quantity - web bonus`).
text:
type: object
description: Subtitles for this item within the offer in each language your storefront supports. The keys of this object are IETF BCP 47 locale codes, e.g. `en-US`.
additionalProperties:
$ref: '#/components/schemas/OfferItemText'
text:
type: object
description: Text for this offer in each language your storefront supports. The keys of this object are IETF BCP 47 locale codes, e.g. `en-US`.
additionalProperties:
$ref: '#/components/schemas/OfferText'
OfferText:
type: object
description: A Neon localized text object for an Offer. See [here](https://neonpay.readme.io/docs/text-localization) for more details.
required:
- name
- description
properties:
name:
description: The translated name of this offer.
type: string
example: 110 Gems
description:
description: The translated description for this offer.
type:
- string
- 'null'
example: Get 100 gold every day you log in to play.
bannerText:
description: The translated banner text for this offer.
type:
- string
- 'null'
example: Great Value
promoText:
description: The translated promo text for this offer.
type:
- string
- 'null'
example: Great Value
theme:
description: The translated theme for this offer.
type:
- string
- 'null'
example: Great Value
subtitle:
description: The translated base portion of the subtitle, used to provide context on this item.
type:
- string
- 'null'
example: 100 credits
highlightedSubtitle:
description: The translated highlighted portion of the subtitle, used to highlight any additional value gained from this purchase.
type:
- string
- 'null'
example: +10 extra credits
ItemText:
type: object
description: A Neon localized text object for an Item. See [here](https://neonpay.readme.io/docs/text-localization) for more details.
required:
- nameSingular
- namePlural
properties:
nameSingular:
type: string
description: The translated singular form of this item.
example: gem
namePlural:
type: string
description: The translated plural form of this item.
example: gems
description:
type:
- string
- 'null'
description: A translated description for this item.
APIError:
type: object
required:
- code
- message
properties:
statusCode:
type: number
description: The HTTP response code
example: 400
code:
type: string
description: An error code that is static and can be used for programmatic error handling
example: INVALID_IMAGE_FILE_NAME
message:
type: string
description: A human readable description of the error
example: 'No images were found matching the fil
# --- truncated at 32 KB (45 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/neon-commerce/refs/heads/main/openapi/neon-commerce-storefront-api-openapi.yml