# Interfaces

Interface standards resource for the GunSpec SDK. Wraps `/v1/interfaces`: the mount vocabulary every fit is computed from (`thread:1/2x28`, `mag:stanag`, `rail:picatinny`). Listing it is open; asking which firearms expose a standard is Studio.

Source: https://docs.gunspec.io/en/sdk/interfaces

## client.interfaces.list()

`GET /v1/interfaces`

Auth: API key required  
Tier: Explorer+

Every standard the vocabulary knows, optionally one `kind` only. Answers 304.

### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `kind` | string | no | One kind only |
| `If-None-Match` | string | no | The `ETag` from a previous response. If the body would be byte-identical, the API answers `304 Not Modified` with no body. A 304 counts toward the per-minute rate limit but not the daily request allowance. |

### Response 200 (application/json)

| Field | Type | Description |
| --- | --- | --- |
| `data` | InterfaceStandard[] | The response payload. |
| `data[].id` | string | Kind-prefixed standard id, e.g. `thread:1/2x28`. URL-encode it when addressing `/v1/interfaces/{id}/firearms`. |
| `data[].kind` | string | What sort of interface it is: `thread`, `rail`, `mag`, `stock_mount`, `optic_plate`. |
| `data[].name` | string | Display name, as the maker writes it. |
| `data[].aliases` | string[] | JSON array of alternative spellings of this standard id, as a string. Ids are never renamed; a new spelling becomes an alias. |
| `data[].notes` | string \| null | Free-text notes that do not belong in a specific field. |

```json
{
  "success": true,
  "data": [
    {
      "id": "thread:1/2x28",
      "kind": "thread",
      "name": "1/2-28 UNEF right hand",
      "aliases": [
        "1/2x28",
        "1/2-28"
      ],
      "notes": null
    }
  ]
}
```

### Errors

| Status | Code | Message |
| --- | --- | --- |
| 400 | `VALIDATION_ERROR` | Validation error |
| 401 | `UNAUTHORIZED` | API key required |
| 403 | `FORBIDDEN` | Valid key, not permitted |
| 429 | `RATE_LIMITED` | Rate limit exceeded |
| 500 | `INTERNAL_ERROR` | Unexpected server error |

### Example

```bash
curl --request GET \
  --url 'https://api.gunspec.io/v1/interfaces' \
  --header 'X-API-Key: your_key'
```

## client.interfaces.getFirearms()

`GET /v1/interfaces/{id}/firearms`

Auth: API key required  
Tier: Studio+

Firearms that expose a standard at some position. Studio. The id is URL-encoded for you: `thread:1/2x28` carries a colon and a slash that would otherwise be read as path separators.

### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | Interface standard id. URL-encode it in the path: the colon and any slash must be escaped, so `thread:1/2x28` is sent as `thread%3A1%2F2x28` |

### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | integer | no | Page number, from 1 to 10,000 |
| `per_page` | integer | no | Items per page (max 100) |

### Response 200 (application/json)

| Field | Type | Description |
| --- | --- | --- |
| `data` | object[] | One page of results |
| `data[].id` | string | Slug of the firearm exposing the standard. |
| `data[].name` | string | Display name, as the maker writes it. |
| `data[].position` | string | Where on the firearm the interface sits: `muzzle`, `rear`, `top`, `bottom`. |
| `data[].source` | 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. |
| `data[].confidence` | 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. |
| `data[].manufacturer` | ManufacturerRef \| null | Who makes it. |
| `data[].category` | string \| null | Display name of the firearm category. |
| `data[].images` | InlineMediaItem[] | Renders and photographs of the firearm, ordered so `images[0]` is the frame to show at rest. |
| `data[].images[].id` | integer | Autoincrementing image id. |
| `data[].images[].url` | string | Absolute, directly fetchable URL. |
| `data[].images[].kind` | MediaKind | What kind of asset a media row is. |
| `data[].images[].alt` | string \| null | Alt text, where one has been written. Null otherwise, so do not render an empty string. |
| `data[].images[].width` | integer \| null | Pixel width, where it is known. |
| `data[].images[].height` | integer \| null | Pixel height, where it is known. |
| `data[].svgLineArtUrl` | string \| null | Line-art silhouette, or null where none has been drawn. |
| `data[].yearIntroduced` | integer | Year it entered production or service. Null where the date is disputed or unknown. |
| `pagination.page` | number | Current page number |
| `pagination.per_page` | number | Items per page |
| `pagination.total` | number | Total matching records (Builder and above) |

```json
{
  "success": true,
  "data": [
    {
      "id": "m4a1-carbine",
      "name": "M4A1 Carbine",
      "position": "muzzle",
      "source": "curated",
      "confidence": 1,
      "manufacturer": {
        "id": "magpul",
        "name": "Magpul Industries"
      },
      "category": "Assault Rifle",
      "images": [
        {
          "id": 2572,
          "url": "https://api.gunspec.io/v1/firearms/ak-47/images/2572",
          "kind": "silhouette",
          "alt": "AK-47 right profile",
          "width": 1536,
          "height": 1024
        }
      ],
      "svgLineArtUrl": "https://api.gunspec.io/v1/firearms/m4a1-carbine/media/silhouette",
      "yearIntroduced": 1994
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "per_page": 20,
    "total": 42,
    "totalPages": 3
  }
}
```

### Errors

| Status | Code | Message |
| --- | --- | --- |
| 400 | `VALIDATION_ERROR` | Validation error |
| 401 | `UNAUTHORIZED` | API key required |
| 403 | `FORBIDDEN` | Valid key, not permitted |
| 404 | `NOT_FOUND` | Resource not found |
| 429 | `RATE_LIMITED` | Rate limit exceeded |
| 500 | `INTERNAL_ERROR` | Unexpected server error |

### Example

```bash
curl --request GET \
  --url 'https://api.gunspec.io/v1/interfaces/thread:1%2F2x28/firearms' \
  --header 'X-API-Key: your_key'
```
