GunSpec

Content

Resource class for the GunSpec content feeds. Instantiated internally by the GunSpec client and exposed as client.content.

Optional AuthExplorer+

List published changelog entries, newest first.

listChangelog(params?: ListChangelogParams): Promise<PaginatedResponse<ChangelogEntry>>
GET/v1/changelog

  • stringheader

    Optional. Without a key this endpoint answers under the public policy; a key raises your limits and unlocks plan-gated fields. 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

    Filter by entry category

    Accepts
    Max length
    60

  • ChangelogEntry[]

    One page of results

  • string

    Slug of the entry, taken from the file it was authored in.

  • string

    Entry headline.

  • string

    Entry body, in Markdown.

  • string | null

    What kind of change: feature, improvement, bugfix, data, breaking.

  • string

    When it was published, ISO 8601.

  • integer

    Integer flag, 1 when the entry is live. The public feed only returns published entries, so this is 1 on every row a consumer sees.

  • string

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

  • string

    When it last changed, ISO 8601.

  • number

    Current page number

  • number

    Items per page

  • number

    Total matching records (Builder and above)

  • 400VALIDATION_ERRORValidation error
  • 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.

Optional AuthExplorer+

client.content.getChangelogEntry()

Get a single changelog entry.

getChangelogEntry(id: string | number): Promise<APIResponse<ChangelogEntry>>
GET/v1/changelog/{id}

  • stringheader

    Optional. Without a key this endpoint answers under the public policy; a key raises your limits and unlocks plan-gated fields. Authorization: Bearer <key> is accepted in its place.

  • stringrequired

    Changelog entry id

    Example

  • ChangelogEntry

    The response payload

  • string

    Slug of the entry, taken from the file it was authored in.

  • string

    Entry headline.

  • string

    Entry body, in Markdown.

  • string | null

    What kind of change: feature, improvement, bugfix, data, breaking.

  • string

    When it was published, ISO 8601.

  • integer

    Integer flag, 1 when the entry is live. The public feed only returns published entries, so this is 1 on every row a consumer sees.

  • string

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

  • string

    When it last changed, ISO 8601.

  • 400VALIDATION_ERRORValidation error
  • 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+

List changes to the catalogue: records added, updated, removed and merged, with the fields that moved. Requires an API key.

listChanges(params?: ListChangesParams): Promise<PaginatedResponse<CatalogChange>>
GET/v1/changes

  • 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

    Entries on or after this ISO date or UTC instant, or after this seq

    Max length
    40
    Example
  • string

    Entries on or before this ISO date (the whole day) or UTC instant

    Max length
    40
  • string

    Only changes to this kind of record

    Accepts
  • string

    Only this kind of change

    Accepts
  • string

    Only changes to this manufacturer's firearms, or to the manufacturer itself

    Max length
    100
    Example
  • stringdefaultdesc

    Newest first, or oldest first for reading forward from a seq

    Accepts
    Example

  • object[]

    One change to the catalogue.

  • integer

    The entry's position in the feed. Increases with every entry; store the highest you have read and pass it as since to continue from there.

  • string

    What kind of record changed. catalog is a resynced entry, which belongs to no one record.

  • string | null

    The record's id, for GET /v1/{entity}s/{id}. Null on a resynced entry.

  • string

    created, updated, deleted, merged (folded into the record named by mergedInto), or resynced: too many records changed at once to list, so re-read what you hold.

  • string

    When the change was recorded, ISO 8601 UTC.

  • string | null

    The record's version after the change. Null for a removal.

  • string | null

    For merged, the id of the record it was folded into. An old id also answers with that record.

  • string | null

    The record's name when it changed, kept after it is removed.

  • object | null

    The maker of a firearm, or the manufacturer itself, when it changed.

  • string

    Manufacturer id.

  • string | null

    Manufacturer name.

  • object[]

    For updated, the fields that moved. Null when the change happened before an earlier version of the record had been kept, so it is known to have changed and no more.

  • string

    The field as the record names it; a nested field is a dotted path.

  • unknown

    The value before the change. Null when the field was empty.

  • unknown

    The value after the change. Null when the field was emptied.

  • boolean

    Present and true when a long value was cut to its start; the record holds the rest.

  • boolean

    Present and true when your plan does not include this field: it moved, and before and after are null.

  • integer | null

    For resynced, how many records the rewrite touched.

  • object[]

    A firearm's current pictures, for showing the entry. Empty for a removed record and for other kinds of record.

  • integer

    Image id.

  • string

    Where to fetch it.

  • string

    What kind of picture it is.

  • string | null

    Alternative text.

  • integer | null

    Width in pixels.

  • integer | null

    Height in pixels.

  • object[]

    The quality tasks behind the change, at most three, newest first: the task on the same record and field whose fix or accepted answer closed it, up to two days after or sixty days before the change. Empty when none is linked.

  • integer | null

    The task's number, for GET /v1/data/tasks/{id}.

  • string

    The task's key.

  • string

    What kind of task it is.

  • string | null

    The quality check that raised it.

  • string

    The check's name, readable.

  • string | null

    What the check found on this record, in one sentence.

  • string

    fixed where the record was corrected so the check no longer finds it; otherwise how an accepted answer ended.

  • string | null

    When the task closed.

  • object | null

    What the research found: the value a source states and the page, or why the value was removed. Null when nothing was recorded, or when the task is withheld.

  • boolean

    Present and true when every field the task concerns is above your plan: finding is null and why is the check's rule.

  • string

    The task's public page.

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

Optional AuthExplorer+

List published blog posts, newest first.

listBlogPosts(params?: ListBlogPostsParams): Promise<PaginatedResponse<BlogPost>>
GET/v1/blog

  • stringheader

    Optional. Without a key this endpoint answers under the public policy; a key raises your limits and unlocks plan-gated fields. 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

    Filter by post category

    Max length
    60
    Example

  • BlogPost[]

    A published post. Both endpoints serve the stored row; body is markdown.

  • string

    Opaque post id. A string, not a number: posts are keyed like every other authored record here.

  • string

    URL-safe slug, and what /v1/blog/{slug} addresses.

  • string

    Post headline.

  • string | null

    One-line description, for a card or a feed. Null where the author wrote none.

  • string | null

    The post itself, as markdown.

  • string | null

    Path of the hero image on the assets CDN, or null. Prefix it with the assets host to fetch.

  • string | null

    What the hero image shows, as alt text. Null where the post has no hero or none was written.

  • string | null

    Editorial category, e.g. guides. Null where the post has none.

  • string

    Always published on these endpoints: a draft is not served publicly.

  • string | null

    When the post was published, which is what the list orders by. Null on a post never given a date.

  • string

    When the post was first written, YYYY-MM-DD HH:MM:SS in UTC. Not the publication date: postedAt is.

  • string

    When the post was last edited, YYYY-MM-DD HH:MM:SS in UTC.

  • object | null

    Who wrote the post: the display name on the account that created it, never its address. Null when that account has no display name, and the post is then attributed to the publisher.

  • string

    The author's display name, as set on their GunSpec account.

  • string

    URL segment of the author's page on the blog, made from their display name.

  • string

    Which avatar style the author chose on their account.

  • string

    Seed the avatar is drawn from. Stable per author, and not their account id.

  • number

    Current page number

  • number

    Items per page

  • number

    Total matching records (Builder and above)

  • 400VALIDATION_ERRORValidation error
  • 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.

Optional AuthExplorer+

client.content.getBlogPost()

Get a single blog post, including its full body.

getBlogPost(slug: string): Promise<APIResponse<BlogPost>>
GET/v1/blog/{slug}

  • stringheader

    Optional. Without a key this endpoint answers under the public policy; a key raises your limits and unlocks plan-gated fields. Authorization: Bearer <key> is accepted in its place.

  • stringrequired

    Blog post slug

    Accepts
    a lowercase slug: letters, digits and hyphens
    Example

  • object

    The response payload.

  • BlogPost

    A published post. Both endpoints serve the stored row; body is markdown.

  • string

    Opaque post id. A string, not a number: posts are keyed like every other authored record here.

  • string

    URL-safe slug, and what /v1/blog/{slug} addresses.

  • string

    Post headline.

  • string | null

    One-line description, for a card or a feed. Null where the author wrote none.

  • string | null

    The post itself, as markdown.

  • string | null

    Path of the hero image on the assets CDN, or null. Prefix it with the assets host to fetch.

  • string | null

    What the hero image shows, as alt text. Null where the post has no hero or none was written.

  • string | null

    Editorial category, e.g. guides. Null where the post has none.

  • string

    Always published on these endpoints: a draft is not served publicly.

  • string | null

    When the post was published, which is what the list orders by. Null on a post never given a date.

  • string

    When the post was first written, YYYY-MM-DD HH:MM:SS in UTC. Not the publication date: postedAt is.

  • string

    When the post was last edited, YYYY-MM-DD HH:MM:SS in UTC.

  • 400VALIDATION_ERRORValidation error
  • 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.

Optional AuthExplorer+

The notices the website is showing right now, best first. Public, cached for a minute at the edge. An empty list means no banner.

listNotices(): Promise<APIResponse<{ notices: SiteNotice[] }>>
GET/v1/notices

  • stringheader

    Optional. Without a key this endpoint answers under the public policy; a key raises your limits and unlocks plan-gated fields. Authorization: Bearer <key> is accepted in its place.

  • object

    The response payload.

  • SiteNotice[]

    Published notices inside their display window, best first: highest priority, then newest.

  • string

    Row id of the notice. The website keys its dismissal on this, so a new notice is seen even by a reader who dismissed the last one.

  • string

    Short label shown before the message.

  • string

    The sentence shown in the banner.

  • string

    A second line, shown under the highlight where one is set.

  • NoticeVariant

    How prominently a site notice is shown.

  • string | null

    Text of the call to action, or null when the banner has none.

  • string | null

    Where the call to action goes.

  • integer

    Higher sorts first. Ties break on newest.

  • string | null

    When the notice becomes visible. Null means immediately.

  • string | null

    When it stops being shown. This is why notices are rows rather than copy: an end date is the only version of "take this down later" that does not rely on somebody remembering.

  • 400VALIDATION_ERRORValidation error
  • 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.