GunSpec

Vendor

Vendor (seller) resource for the GunSpec SDK. Wraps /v1/vendor/* and the outbound click route. A seller holds an Enterprise plan and names one of their ordinary keys in Profile > Seller; that mapping is the whole vendor scope, so there is no separate credential to configure here. A key no shop names answers 403 KEY_NOT_LINKED_TO_SHOP. A feed reads before it writes: shops() tells a script which ids it can act for, listOffers() returns what the API holds, and updateOffer() changes one field without resending the rest.

Auth RequiredEnterprise

The shops this key may act for. A script learns its shop ids here.

shops(): Promise<APIResponse<VendorShop[]>>
GET/v1/vendor/shops

  • stringheaderrequired

    Your API key. Authorization: Bearer <key> is accepted in its place.

  • object[]

    The response payload.

  • string

    Slug of the shop. This is the value to send as ?vendor=.

  • string

    Display name, as the maker writes it.

  • string | null

    Official website, where one is known.

  • string | null

    ISO 4217 code the price is in, e.g. AUD. Prices are integer minor units; format with Intl.NumberFormat at render rather than dividing first.

  • boolean

    Whether staff have approved the shop. An unapproved shop accepts writes but shows nothing publicly.

  • 400VALIDATION_ERRORValidation error
  • 401UNAUTHORIZEDAPI key required
  • 403FORBIDDENValid key, not permitted
  • 429RATE_LIMITEDRate limit exceeded
  • 500INTERNAL_ERRORUnexpected server error

Minimum tier
Enterprise
Monthly quota
1,000,000/mo
Rate limit
300/min
Daily cap
50,000

Figures shown are for this endpoint's minimum tier. Higher tiers raise every limit.

Auth RequiredEnterprise

Your listings as the API holds them, stockQty and click counts included.

listOffers(params?: ListVendorOffersParams): Promise<PaginatedResponse<VendorOffer>>
GET/v1/vendor/offers

  • stringheaderrequired

    Your API key. Authorization: Bearer <key> is accepted in its place.

  • string

    Which of your shops to act for. Required only when one key is named by more than one shop; GET /v1/vendor/shops lists them

    Max length
    64
    Example
  • string

    Only parts or only firearms

    Accepts
    Max length
    40
  • string

    Only drafts or only published rows

    Accepts
  • string

    Match on your SKU or the product name

    Max length
    120
    Example
  • integerdefault1

    Page number, from 1 to 10,000

    Range
    1 – 10000
    Example
  • integerdefault20

    Items per page (max 100)

    Range
    1 – 100
    Example

  • object[]

    One page of results

  • string

    The shop's own catalogue key for the listing. A seller's identifier, not ours: it is what PATCH /v1/vendor/offers/{sku} addresses.

  • OfferTargetKind

    What a seller listing is for.

  • string

    Slug of the catalogued record the listing points at, in whichever catalog targetKind names.

  • integer

    Price in integer minor units of currency, so cents for AUD. Never a float. Format with Intl.NumberFormat at render rather than dividing first.

  • string

    ISO 4217 code the price is in, e.g. AUD. Prices are integer minor units; format with Intl.NumberFormat at render rather than dividing first.

  • string

    Absolute, directly fetchable URL.

  • boolean

    Whether the shop reports it in stock. Derived from stockQty where the shop tracks a count.

  • integer | null

    Units you hold: 0 is out of stock, null is not tracked. Private to the shop, and never returned by a public offers endpoint.

  • OfferStatus

    Whether a seller listing is public.

  • string

    Where the record came from: a curated entry, an inference, or an import.

  • integer

    Outbound clicks this listing earned over the last 30 days.

  • string

    When a field we serve last changed.

  • number

    Current page number

  • number

    Items per page

  • number

    Total matching records (Builder and above)

  • 400VALIDATION_ERRORValidation error
  • 401UNAUTHORIZEDAPI key required
  • 403FORBIDDENValid key, not permitted
  • 429RATE_LIMITEDRate limit exceeded
  • 500INTERNAL_ERRORUnexpected server error

Minimum tier
Enterprise
Monthly quota
1,000,000/mo
Rate limit
300/min
Daily cap
50,000

Figures shown are for this endpoint's minimum tier. Higher tiers raise every limit.

Auth RequiredEnterprise

Upsert up to 500 listings keyed by your own SKU. Ids we do not hold come back as unmatched rather than failing the batch; a bad row (a string price, a float) is a 400 with details naming it.

pushOffers(input: PushOffersInput, scope?: VendorScope): Promise<APIResponse<PushOffersResult>>
PUT/v1/vendor/offers

  • stringheaderrequired

    Your API key. Authorization: Bearer <key> is accepted in its place.

  • string

    Which of your shops to act for. Required only when one key is named by more than one shop; GET /v1/vendor/shops lists them

    Max length
    64
    Example

  • object[]required

    The listings to upsert, keyed by your own SKU. Up to 500 per request.

  • object

    The response payload.

  • integer

    Offers accepted and stored.

  • object[]

    Rows naming a record we do not hold. Reported rather than failing the batch, so a mapping error is a review and not a rejected push.

  • string

    The shop's own catalogue key for the listing. A seller's identifier, not ours: it is what PATCH /v1/vendor/offers/{sku} addresses.

  • OfferTargetKind

    What a seller listing is for.

  • string

    The id the row named, which we do not hold.

  • 400VALIDATION_ERRORValidation error
  • 401UNAUTHORIZEDAPI key required
  • 403FORBIDDENValid key, not permitted
  • 413PAYLOAD_TOO_LARGERequest body too large
  • 429RATE_LIMITEDRate limit exceeded
  • 500INTERNAL_ERRORUnexpected server error

Minimum tier
Enterprise
Monthly quota
1,000,000/mo
Rate limit
300/min
Daily cap
50,000

Figures shown are for this endpoint's minimum tier. Higher tiers raise every limit.

Auth RequiredEnterprise

Change one listing. Absent fields are unchanged.

updateOffer(sku: string, input: UpdateOfferInput, scope?: VendorScope): Promise<APIResponse<{ sku: string }>>
PATCH/v1/vendor/offers/{sku}

  • stringheaderrequired

    Your API key. Authorization: Bearer <key> is accepted in its place.

  • stringrequired

    Your own SKU for the offer

    Example

  • string

    Which of your shops to act for. Required only when one key is named by more than one shop; GET /v1/vendor/shops lists them

    Max length
    64
    Example

  • integer

    New price in integer minor units of currency. A float is refused.

  • string

    ISO 4217 code the price is in, e.g. AUD. Prices are integer minor units; format with Intl.NumberFormat at render rather than dividing first.

  • string

    Product page on your shop. Must be a full https:// address; any other scheme is refused.

  • integer

    Units you hold: 0 is out of stock, null is not tracked. Send this or in_stock, never both: a row carrying a quantity derives its flag from it.

  • boolean

    Stock flag, for a shop that does not count units. Send this or stock_qty, never both.

  • string | null

    ISO 3166-1 alpha-2 code you ship to. Null states no restriction.

  • string

    Set published to show the listing on public pages, or draft to take it off them while keeping it.

  • object

    The response payload.

  • string

    The shop's own catalogue key for the listing. A seller's identifier, not ours: it is what PATCH /v1/vendor/offers/{sku} addresses.

  • 400VALIDATION_ERRORValidation error
  • 401UNAUTHORIZEDAPI key required
  • 403FORBIDDENValid key, not permitted
  • 404NOT_FOUNDResource not found
  • 413PAYLOAD_TOO_LARGERequest body too large
  • 429RATE_LIMITEDRate limit exceeded
  • 500INTERNAL_ERRORUnexpected server error

Minimum tier
Enterprise
Monthly quota
1,000,000/mo
Rate limit
300/min
Daily cap
50,000

Figures shown are for this endpoint's minimum tier. Higher tiers raise every limit.

Auth RequiredEnterprise

Withdraw one listing.

deleteOffer(sku: string, scope?: VendorScope): Promise<APIResponse<{ removed: boolean }>>
DELETE/v1/vendor/offers/{sku}

  • stringheaderrequired

    Your API key. Authorization: Bearer <key> is accepted in its place.

  • stringrequired

    Your own SKU for the offer

    Example

  • string

    Which of your shops to act for. Required only when one key is named by more than one shop; GET /v1/vendor/shops lists them

    Max length
    64
    Example

  • object

    The response payload.

  • boolean

    Always true: the SKU is not listed once this returns, whether or not it was before.

  • 400VALIDATION_ERRORValidation error
  • 401UNAUTHORIZEDAPI key required
  • 403FORBIDDENValid key, not permitted
  • 429RATE_LIMITEDRate limit exceeded
  • 500INTERNAL_ERRORUnexpected server error

Minimum tier
Enterprise
Monthly quota
1,000,000/mo
Rate limit
300/min
Daily cap
50,000

Figures shown are for this endpoint's minimum tier. Higher tiers raise every limit.

PublicExplorer+

The tracked outbound link for an offer's clickId. Render this as the href: the API counts the visit and 302s to the shop, so the seller can check our figure against their own analytics.

clickUrl(clickId: string, locale?: 'en' | 'de'): string
GET/v1/out/{clickId}

No authentication. This endpoint answers without a key.

  • stringrequired

    The listing's tracking token, from clickId on an offer

  • string

    Locale for the catalog page a lapsed listing falls back to

    Accepts

  • 404NOT_FOUNDResource not found
  • 429RATE_LIMITEDRate limit exceeded
  • 500INTERNAL_ERRORUnexpected server error

Minimum tier
Explorer+
Monthly quota
200/mo
Rate limit
10/min
Daily cap
50

Figures shown are for this endpoint's minimum tier. Higher tiers raise every limit.

PublicExplorer+

Follow a click server-side and return the shop URL it lands on. The API counts this as a visit exactly as a browser's would; use it for a link checker, not for rendering. null when the runtime hides cross-origin redirects (browsers do).

resolveClick(clickId: string): Promise<string | null>
GET/v1/out/{clickId}

No authentication. This endpoint answers without a key.

  • stringrequired

    The listing's tracking token, from clickId on an offer

  • string

    Locale for the catalog page a lapsed listing falls back to

    Accepts

  • 404NOT_FOUNDResource not found
  • 429RATE_LIMITEDRate limit exceeded
  • 500INTERNAL_ERRORUnexpected server error

Minimum tier
Explorer+
Monthly quota
200/mo
Rate limit
10/min
Daily cap
50

Figures shown are for this endpoint's minimum tier. Higher tiers raise every limit.