GunSpec

Seller

A shop reaches these endpoints in four steps, and the third is the one nothing else explains.

  1. Hold an Enterprise plan. Listings are a plan perk. Nothing in these tables bills anyone and there is no separate advertising product.
  2. Apply, and be approved by a person. Apply at https://gunspec.io/en/sellers. Approval creates the shop; until then nothing of yours is public.
  3. Name a key. There is no such thing as a "vendor key" and no scope column on keys. You create an ordinary API key, then name it on the shop in Profile > Seller > Shop settings > Pushing from a server. That mapping is the entire vendor scope: the shop says which key it accepts a push from, and your key value is never sent to us. Several shops may name the same key; when they do, every call below needs ?vendor=, and GET /v1/vendor/shops lists the ids that key may act for.
  4. Read, then write. GET /v1/vendor/offers for what we hold, PATCH for a price or stock change, PUT for a bulk upsert, DELETE to withdraw. Read first and a nightly sync sends the rows that changed rather than all of them.

Four rules the API enforces and a retailer usually meets late:

  • Money is integer minor units plus an ISO 4217 code. 139900 with AUD is A$1,399.00. A float is refused at the boundary rather than rounded quietly. Minor units are not always hundredths: JPY has none, KWD has three. Send the units of the currency you name.
  • `stock_qty` is private and never appears in a public response. 0 renders as "No stock at this supplier", any other number as in stock, null as not tracked. A live count is competitive information, so we store it and never publish it. If you do not count units, send in_stock instead: a row that carries a quantity derives the flag from it, so the two cannot disagree.
  • Writing is also a claim that the price still stands. An offer nobody has refreshed in 30 days from a feed (90 from the console) stops appearing, because a stale price is worse than none. Re-pushing an unchanged row is how you say nothing changed.
  • A mapping error is a review, not a rejected batch. SKUs naming an id we do not hold come back in unmatched. A file of 400 rows is not refused because three ids were wrong.

GunSpec never takes the order. An offer carries a URL and links out; there is no basket, payment or customer anywhere in this surface. Public rows link through /v1/out/{clickId}, which counts the visit and redirects to you, so the traffic we send is measurable - read it in Profile > Seller > Traffic. region on an offer hides sellers who do not ship somewhere: a display convenience, never a statement about what is lawful to own.

Authentifizierung erforderlichEnterprise

Upserts up to 500 offers keyed by your own SKU. Each offer names exactly one of attachment_id or firearm_id: a SKU is a part or a firearm, never both. A seller maps their catalog to ours once; SKUs naming an id we do not hold come back in unmatched rather than failing the batch, so a mapping error is a review and not a rejected push. Re-pushing an unchanged offer is how you say the price still stands, which is what keeps it out of the 30-day staleness sweep. Prices are integer minor units with an ISO 4217 currency; a float is refused, and currency may be omitted to use your account default. Minor units are not always hundredths (JPY has none and KWD has three), so send the units of the currency you name. Requires an Enterprise key registered to a vendor.

PUT/v1/vendor/offers

  • stringHeadererforderlich

    Ihr API-Schlüssel. Authorization: Bearer <key> wird ebenfalls akzeptiert.

  • 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. Länge
    64
    Beispiel

  • object[]erforderlich

    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

Each offer names exactly one of attachment_id or firearm_id. A SKU is a part or a firearm, never both.

currency may be omitted to use the shop default, so a seller pricing everything in one currency sets it once rather than on all 500 rows.

Chunk a larger catalogue. A shop may hold 2,000 listings in total.

Mindeststufe
Enterprise
Monatskontingent
1,000,000/mo
Anfragerate
300/min
Tageslimit
50,000

Die Werte gelten für die Mindeststufe dieses Endpunkts. Höhere Stufen erhöhen alle Limits.