---
title: "List new firearm models"
method: GET
path: "/v1/releases"
tags: ["Releases"]
---

# List new firearm models

`GET /v1/releases`

## Request

- Base URL: `https://api.gunspec.io`
- URL: `https://api.gunspec.io/v1/releases`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Returns new firearm models, newest announcement first, each with the date it was announced, the date GunSpec first read it, its alternate names and the pages that name it. A model appears only after research has read a source a reader can cite (the maker, a standards body, a government, a reference work or the press) and quoted the words that name it; a headline alone never makes a row. `status` says whether the catalog holds a record yet (`catalogued`, with `catalogueId`) or not (`announced`). Filter by day with `since` and `until`: they apply to `announcedAt`, or to the day GunSpec first read the model with `order=consumed`. A model with no dated source counts from the day it was first read.

Available on every plan. Requires an API key; Explorer keys receive a reduced field set.

## Query parameters

- `page` integer
- `per_page` integer
- `since` string
- `until` string
- `maker` string
- `status` 'announced' | 'catalogued'
- `q` string
- `order` 'announced' | 'consumed'

## Response `200`

List new firearm models

- object
  - `success` boolean, required: Always true on a successful response. Every error carries `false` and an `error` object instead.
  - `data` object[], required: One page of results. Use `pagination` to walk the rest.
    - `id` string: Stable id of the release row.
    - `slug` string: The id the catalog gives the model once it holds a record. Informational: it can change if research settles a different name, so key on `id`.
    - `name` string: The model's name as the maker writes it, settled by research from a page that states it.
    - `alternateNames` string[]: Other names the sources give the model. Each appears on a page research read; none is inferred.
    - `manufacturer` object, nullable: The maker. `id` is the catalog manufacturer id, or null when the catalog holds no record of the maker yet.
      - `id` string, nullable, required: Catalog manufacturer id.
      - `name` string, required: Maker name.
    - `status` 'announced' | 'catalogued': Whether the catalog holds a record for the model yet.
    - `catalogueId` string, nullable: The firearm id once `status` is `catalogued`, for `GET /v1/firearms/{id}`. Null before.
    - `announcedAt` string, nullable: The date (`YYYY-MM-DD`) of the earliest source a reader can cite that names the model. Null when no source carried a date.
    - `releasedAt` string, nullable: When a source says the model ships or goes on sale, at the precision it gave: `YYYY`, `YYYY-MM` or `YYYY-MM-DD`. Null when no source states a date. "Spring 2027" is not a date and is never turned into one.
    - `releasedPrecision` 'year' | 'month' | 'day' | 'null', nullable: How much of `releasedAt` the source gave.
    - `firstSeenAt` string: When GunSpec first read the model (UTC): the date we consumed it. Always present.
    - `updatedAt` string: When the row last changed (UTC).
    - `bestSourceKind` 'manufacturer' | 'standards_body' | 'government' | 'peer_reviewed' | 'reference' | 'aggregator' | 'press' | 'retailer' | 'community' | 'other' | 'null', nullable: The strongest kind among `sources`, strongest first: the maker's own page, a standards body, a government, a reference work, then press.
    - `sources` object[]: The pages that name the model, oldest first. Every release has at least one of a citable kind.
      - `url` string: A page that names the model. Open it to check the claim.
      - `kind` 'manufacturer' | 'standards_body' | 'government' | 'peer_reviewed' | 'reference' | 'aggregator' | 'press' | 'retailer' | 'community' | 'other': What kind of page it is (`SourceKind`).
      - `publisher` string, nullable: Who published it, when known.
      - `publishedAt` string, nullable: The page's own date (`YYYY-MM-DD`), when it carried one.
  - `pagination` Pagination: Page-size is reported under both `per_page` (matching the request parameter) and `limit` (retained for existing integrations). They always carry the same value. `total` and `totalPages` are omitted for Explorer and anonymous callers.
    - `page` integer, required: The page this response is, 1-based.
    - `per_page` integer, required: Page size. Same value as `limit`.
    - `limit` integer, required: Page size. Alias of `per_page`.
    - `total` integer: Total records matching the query across every page.
    - `totalPages` integer: How many pages the result set spans at the current `per_page`.

## Other responses

- `400`: Validation error
- `401`: Missing or invalid API key
- `403`: The credential is valid and the caller is not permitted. Three causes, none of which reissuing a key changes: the plan is below the endpoint's tier, the account is suspended, or the key is not attached to the thing being acted on, meaning a user account for `/v1/me` or a shop for `/v1/vendor`. Distinct from 401, which means the credential is missing, malformed or expired and a new one can work.
- `429`: A limit was reached. `RATE_LIMITED` is the per-minute limit: wait `Retry-After` seconds (a minute) and retry. `DAILY_CAP_EXCEEDED` is the plan's daily limit, per key: nothing will be served until the counters return to zero at midnight UTC. `MONTHLY_CAP_EXCEEDED` is the plan's monthly allowance, for the whole account: nothing will be served until midnight UTC on the first of next month, or until the plan changes. For both, `Retry-After` is the seconds until then and `error.resetsAt` says when as an instant. Calls made after a refusal are refused too and do not spend the month, and a free key that keeps calling is paused, so stop at the first one and resume at the reset.
- `500`: Internal server error

---

[API](https://skmtc.dev/gunspec/apis/gunspec-io-api.md) · [All operations](https://skmtc.dev/gunspec/apis/gunspec-io-api/llms.txt) · [OpenAPI document](https://skmtc.dev/gunspec/apis/gunspec-io-api/revisions/f2e974d8b05c?raw)
