GunSpec

Attachments

Resource class for attachments and their compatibility.

Auth RequiredExplorer+

List attachments. fits and only_offered change what the list means: the first runs the fit engine, the second restricts to one seller's stock.

list(params?: ListAttachmentsParams): Promise<PaginatedResponse<Attachment>>
GET/v1/attachments

  • stringheaderrequired

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

  • integerdefault1

    Page number, from 1 to 10,000

    Range
    1 – 10000
    Example
  • integerdefault20

    Items per page (max 100)

    Range
    1 – 100
    Example
  • string

    Attachment category

    Max length
    100
    Example
  • string

    Manufacturer slug

    Max length
    100
    Example
  • string

    Only attachments that fit this firearm

    Max length
    100
    Example
  • string

    Only attachments requiring this interface standard

    Max length
    80
    Example
  • string

    Substring match on name

    Max length
    60
    Example
  • boolean

    Only factory parts (true) or only aftermarket (false)

  • string

    Production status. The catalog keeps discontinued parts on purpose, so a store front asks for in_production

    Accepts
    Example
  • string

    Restrict to one seller. me resolves to the vendor your key belongs to

    Max length
    64
    Example
  • boolean

    Drop anything that seller does not currently stock. Needs a resolvable vendor, and yields nothing without one

  • Attachment[]

    One page of results

  • string

    URL-safe slug identifying the part, e.g. magpul-zhukov-s-stock.

  • string

    Display name, as the maker writes it.

  • string

    What kind of part it is: stock, optic, muzzle, magazine, grip.

  • ManufacturerRef | null

    Who makes it.

  • string | null

    The maker's own SKU, where they publish one.

  • number | null

    Weight in grams.

  • number | null

    Length in millimetres.

  • integer | null

    Magazines only

  • number | null

    Suppressors and muzzle devices

  • string | null

    The mount position this part occupies, or null when it takes none.

  • boolean

    True when the part ships on the firearm from the factory. A factory part carries no statMods or specDeltas, because the firearm's own figures already include it.

  • string | null

    The firearm this is the factory part for, when isFactoryPart is true.

  • object

    Editorial adjustments to the game statistics once fitted, keyed by stat. Same status as game_* on a firearm: not measured.

  • object

    Specification changes once fitted, keyed by field: a folding stock changes the folded length, for example.

  • string | null

    Absolute URL of the manufacturer product photo on the assets CDN, ready to render. Null when no photo has been sourced yet.

  • AttachmentStatus

    Production status of an attachment. limited corresponds to a firearm's limited_production.

  • number | null

    How completely the record is specified and how well it is sourced, 0 to 1. A record-level completeness and provenance measure, not a per-field probability of correctness. Use it to rank and triage; use sources to verify an individual number.

  • string

    When a field we serve last changed. Maintained by the database rather than by whatever wrote the row, so it moves for a corrected specification and does not move for a re-run of the importer.

  • string | null

    Opaque fingerprint of this record. It changes when and only when a field we serve changes, so a client holding the same value already has the record and need not fetch it. Equality is the only supported operation: do not parse it, and do not assume how it is computed. Null means the record has not been written since versioning began, not that it is unchanged.

  • string[]

    Standard ids this adds to the firearm once fitted. Resolved to { id, name, kind } rows on /v1/attachments/{id}.

  • 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
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.

This read answers conditional requests. Keep the ETag from a response and send it back as If-None-Match: an unchanged record returns 304 Not Modified with no body, which counts toward your per-minute rate limit but not your daily allowance.

Auth RequiredExplorer+

Get one attachment with its requirements, provisions and caliber ratings.

get(id: string): Promise<APIResponse<AttachmentDetail>>
GET/v1/attachments/{id}

  • stringheaderrequired

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

  • stringrequired

    Attachment slug

    Accepts
    a lowercase slug: letters, digits and hyphens
    Example

  • AttachmentDetail

    The response payload

  • string

    URL-safe slug identifying the part, e.g. magpul-zhukov-s-stock.

  • string

    Display name, as the maker writes it.

  • string

    What kind of part it is: stock, optic, muzzle, magazine, grip.

  • ManufacturerRef | null

    Who makes it.

  • string | null

    The maker's own SKU, where they publish one.

  • number | null

    Weight in grams.

  • number | null

    Length in millimetres.

  • integer | null

    Magazines only

  • number | null

    Suppressors and muzzle devices

  • string | null

    The mount position this part occupies, or null when it takes none.

  • boolean

    True when the part ships on the firearm from the factory. A factory part carries no statMods or specDeltas, because the firearm's own figures already include it.

  • string | null

    The firearm this is the factory part for, when isFactoryPart is true.

  • object

    Editorial adjustments to the game statistics once fitted, keyed by stat. Same status as game_* on a firearm: not measured.

  • object

    Specification changes once fitted, keyed by field: a folding stock changes the folded length, for example.

  • string | null

    Absolute URL of the manufacturer product photo on the assets CDN, ready to render. Null when no photo has been sourced yet.

  • AttachmentStatus

    Production status of an attachment. limited corresponds to a firearm's limited_production.

  • number | null

    How completely the record is specified and how well it is sourced, 0 to 1. A record-level completeness and provenance measure, not a per-field probability of correctness. Use it to rank and triage; use sources to verify an individual number.

  • string

    When a field we serve last changed.

  • string | null

    Opaque fingerprint of this record. It changes when and only when a field we serve changes, so a client holding the same value already has the record and need not fetch it. Equality is the only supported operation: do not parse it, and do not assume how it is computed. Null means the record has not been written since versioning began, not that it is unchanged.

  • string | null

    Prose summary of the record, where one has been written.

  • object

    Category-specific facts

  • string[]

    JSON array of the pages the figures were taken from, as a string.

  • string | null

    Page the asset or document was taken from.

  • Provenance

    Where a record's figures came from and how far they have been checked, in one place. sources are the pages consulted; check a specific figure against those. sourceKinds says what each page is and bestSourceKind the strongest of them, on the hierarchy SourceKind defines: a maker or standards-body page is evidence for a figure, a retailer or forum page is evidence the item exists. dataConfidence is the 0 to 1 score set from what was actually sourced and never raised by hand. verifiedAt and verifiedFields say when a source was last read against the record and which fields it stated; null means the row is still seed knowledge. updatedAt and version are the same cache signals the record carries at the top level.

  • string[]

    The pages consulted when the record was compiled, as an array. Check a specific figure against these rather than against dataConfidence.

  • object[]

    What each cited page is, in sources order, on the SourceKind hierarchy. A host not in the source map is other, never guessed.

  • SourceKind | null

    The strongest kind among the citations, or null when nothing is cited. manufacturer or standards_body means a figure can be checked against an authority; retailer or community alone means the record is still supported by copies of copies.

  • number | null

    The 0 to 1 score set from what was actually sourced, never raised by hand. See the confidence bands in the docs.

  • string | null

    When a source was last read against this record. Null means the row is still seed knowledge.

  • string[]

    Which fields the source stated, as an array. Everything else on a verified row is still unverified. Null where no source has been read.

  • string | null

    Cartridges only: the page the drawing figures were taken from. Null on every other kind of record.

  • string

    When a served column last changed; the same value the record carries at the top level.

  • string | null

    The record's content version, equal to the top-level version; equal versions mean equal data.

  • integer | null

    Year it entered production or service. Null where the date is disputed or unknown.

  • StandardRef[][]

    Requirement groups. One standard from each group must be present on the firearm. Empty means universal fit.

  • StandardRef[]

    Standards this adds to the firearm once fitted, resolved to { id, name, kind }.

  • string

    Kind-prefixed standard id.

  • string

    Display name, as the maker writes it.

  • string

    What sort of interface it is.

  • object[]

    What this part is rated for, where being rated matters, meaning suppressors and magazines. The caliber, bore and minimum-barrel gate is checked against these and is never bridged or inferred.

  • string

    Slug of the cartridge. Resolve against /v1/calibers/{id}.

  • string | null

    Display name of the cartridge.

  • number | null

    Shortest barrel in millimetres this part is rated for in that cartridge. Null where the maker states none.

  • boolean

    Whether the maker rates it for automatic fire in that cartridge.

  • string | null

    Free-text notes that do not belong in a specific field.

  • integer

    Number of firearms with a curated override for this attachment

  • string

    When the record was first added, YYYY-MM-DD HH:MM:SS in UTC.

  • 400VALIDATION_ERRORValidation error
  • 401UNAUTHORIZEDAPI key required
  • 403FORBIDDENValid key, not permitted
  • 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.

This read answers conditional requests. Keep the ETag from a response and send it back as If-None-Match: an unchanged record returns 304 Not Modified with no body, which counts toward your per-minute rate limit but not your daily allowance.

Auth RequiredStudio+

List the firearms an attachment fits, with how each fit was reached. Studio.

getFirearms(id: string, params?: PaginationParams): Promise<PaginatedResponse<AttachmentFirearmFit>>
GET/v1/attachments/{id}/firearms

  • stringheaderrequired

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

  • stringrequired

    Attachment slug

    Accepts
    a lowercase slug: letters, digits and hyphens
    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

    Slug of the firearm the attachment fits.

  • string

    Display name, as the maker writes it.

  • FitType | null

    How it fits: direct on the firearm own interface, adapter through the part named in adapter, or curated from an override on the attachment. Null when it does not fit.

  • FitSource | null

    The weakest evidence behind the fit.

  • number

    How well evidenced this row is, 0 to 1. A minimum, not an average: an inferred row caps every fit computed through it, and min_confidence on the endpoint hides rows below a threshold.

  • string

    Plain-language account of why it fits, safe to show in a UI.

  • FitVia[]

    The interfaces that satisfied the attachment requirements, with where each came from.

  • string

    Where on the firearm the interface sits: muzzle, rear, top, bottom.

  • string

    Id of the interface standard, kind-prefixed, e.g. thread:1/2x28. Ids are never renamed; new spellings become aliases.

  • InterfaceSource

    Where an interface row on a firearm came from. curated is a person; inferred is the backfill, capped at 0.6 confidence; the inherited kinds came through the parent chain or a platform.

  • string | null

    The adapter that bridges this fit, or null when none is needed. Threads, magazine wells and the caliber gate are never bridged.

  • AdapterRef | null

    The adapter the fit goes through, when fitType is adapter. Null for a direct or curated fit.

  • ManufacturerRef | null

    Who makes it.

  • string | null

    Display name of the firearm category.

  • InlineMediaItem[]

    Renders and photographs of the firearm, ordered so images[0] is the frame to show at rest.

  • integer

    Autoincrementing image id.

  • string

    Absolute, directly fetchable URL.

  • MediaKind

    What kind of asset a media row is.

  • string | null

    Alt text, where one has been written. Null otherwise, so do not render an empty string.

  • integer | null

    Pixel width, where it is known.

  • integer | null

    Pixel height, where it is known.

  • string | null

    Line-art silhouette, or null where none has been drawn.

  • integer

    Year it entered production or service. Null where the date is disputed or unknown.

  • 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
  • 404NOT_FOUNDResource not found
  • 429RATE_LIMITEDRate limit exceeded
  • 500INTERNAL_ERRORUnexpected server error

Minimum tier
Studio+
Monthly quota
150,000/mo
Rate limit
120/min
Daily cap
10,000

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

Auth RequiredExplorer+

Sellers stocking this attachment. Link out through clickUrl with each offer's clickId so the seller can see the visit came from you.

getOffers(id: string, params?: OffersParams): Promise<APIResponse<PublicOffer[]>>
GET/v1/attachments/{id}/offers

  • stringheaderrequired

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

  • stringrequired

    Attachment slug

    Accepts
    a lowercase slug: letters, digits and hyphens
    Example

  • string

    ISO 3166-1 alpha-2 code; hides sellers who do not ship there

    Example

  • PublicOffer[]

    The response payload.

  • object

    The shop stocking the part.

  • string

    Slug of the shop.

  • string

    Display name, as the maker writes it.

  • string | null

    Official website, where one is known.

  • string | null

    Absolute URL of the logo, or null where none is on file.

  • 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.

  • 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.

  • string | null

    Opaque token for the outbound link: send readers to /v1/out/{clickId} so the visit is counted for the seller. Null on a listing that cannot currently be followed.

  • string | null

    ISO 3166-1 alpha-2 code the seller ships to. Null means they state no restriction.

  • string

    When the seller last refreshed this listing. A listing not refreshed inside its freshness window is hidden rather than shown stale.

  • 400VALIDATION_ERRORValidation error
  • 401UNAUTHORIZEDAPI key required
  • 403FORBIDDENValid key, not permitted
  • 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.

Auth RequiredExplorer+

Iterate every attachment matching the filters, fetching pages on demand.

listAutoPaging(params?: ListAttachmentsParams): AsyncIterableIterator<Attachment>
GET/v1/attachments

  • stringheaderrequired

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

  • integerdefault1

    Page number, from 1 to 10,000

    Range
    1 – 10000
    Example
  • integerdefault20

    Items per page (max 100)

    Range
    1 – 100
    Example
  • string

    Attachment category

    Max length
    100
    Example
  • string

    Manufacturer slug

    Max length
    100
    Example
  • string

    Only attachments that fit this firearm

    Max length
    100
    Example
  • string

    Only attachments requiring this interface standard

    Max length
    80
    Example
  • string

    Substring match on name

    Max length
    60
    Example
  • boolean

    Only factory parts (true) or only aftermarket (false)

  • string

    Production status. The catalog keeps discontinued parts on purpose, so a store front asks for in_production

    Accepts
    Example
  • string

    Restrict to one seller. me resolves to the vendor your key belongs to

    Max length
    64
    Example
  • boolean

    Drop anything that seller does not currently stock. Needs a resolvable vendor, and yields nothing without one

  • Attachment[]

    One page of results

  • string

    URL-safe slug identifying the part, e.g. magpul-zhukov-s-stock.

  • string

    Display name, as the maker writes it.

  • string

    What kind of part it is: stock, optic, muzzle, magazine, grip.

  • ManufacturerRef | null

    Who makes it.

  • string | null

    The maker's own SKU, where they publish one.

  • number | null

    Weight in grams.

  • number | null

    Length in millimetres.

  • integer | null

    Magazines only

  • number | null

    Suppressors and muzzle devices

  • string | null

    The mount position this part occupies, or null when it takes none.

  • boolean

    True when the part ships on the firearm from the factory. A factory part carries no statMods or specDeltas, because the firearm's own figures already include it.

  • string | null

    The firearm this is the factory part for, when isFactoryPart is true.

  • object

    Editorial adjustments to the game statistics once fitted, keyed by stat. Same status as game_* on a firearm: not measured.

  • object

    Specification changes once fitted, keyed by field: a folding stock changes the folded length, for example.

  • string | null

    Absolute URL of the manufacturer product photo on the assets CDN, ready to render. Null when no photo has been sourced yet.

  • AttachmentStatus

    Production status of an attachment. limited corresponds to a firearm's limited_production.

  • number | null

    How completely the record is specified and how well it is sourced, 0 to 1. A record-level completeness and provenance measure, not a per-field probability of correctness. Use it to rank and triage; use sources to verify an individual number.

  • string

    When a field we serve last changed. Maintained by the database rather than by whatever wrote the row, so it moves for a corrected specification and does not move for a re-run of the importer.

  • string | null

    Opaque fingerprint of this record. It changes when and only when a field we serve changes, so a client holding the same value already has the record and need not fetch it. Equality is the only supported operation: do not parse it, and do not assume how it is computed. Null means the record has not been written since versioning began, not that it is unchanged.

  • string[]

    Standard ids this adds to the firearm once fitted. Resolved to { id, name, kind } rows on /v1/attachments/{id}.

  • 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

Returns an async iterator: it fetches each page as you consume it, so a loop over the whole collection is one statement and one page in memory at a time.

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.

This read answers conditional requests. Keep the ETag from a response and send it back as If-None-Match: an unchanged record returns 304 Not Modified with no body, which counts toward your per-minute rate limit but not your daily allowance.