> ## Documentation Index
> Fetch the complete documentation index at: https://docs.skynetparts.com/llms.txt
> Use this file to discover all available pages before exploring further.

# catalog

> Find one or more parts by part number or part name.

Send a list of part numbers or part names, get back stock, our catalog price and an ID you can use to order each one. Up to 50 parts per request.

```http theme={null}
POST   https://api.skynet-docs.skynetparts.com/public/api/v1/b2b/catalog
```

Requires an API key. See [Authentication](/authentication) for how to get one.

## Headers

| Header          | Required | Value                |
| --------------- | -------- | -------------------- |
| `Authorization` | Yes      | `Bearer sk_live_...` |
| `Content-Type`  | Yes      | `application/json`   |

## Body

<ParamField body="part_numbers" type="string[]">
  List of manufacturer part numbers most reliable.
</ParamField>

<ParamField body="part_names" type="string[]">
  List of part names or descriptions use when you don't have the exact number.
</ParamField>

<ParamField body="in_stock" default="false" type="boolean">
  When `true`, only parts with stock on hand (`available_stock > 0`) are returned. Defaults to `false` (all matches).
</ParamField>

Send at least one of the two arrays. You may send both results merge. Maximum 50 entries total.

<RequestExample>
  ```bash curl theme={null}
  curl -X POST https://api.skynet-docs.skynetparts.com/public/api/v1/b2b/catalog \
    -H "Authorization: Bearer $SKYNET_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "part_numbers": ["MS21042L3", "AN3-5A"] }'
  ```

  ```javascript Node theme={null}
  const res = await fetch("https://api.skynetparts.com/public/api/v1/b2b/catalog", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.SKYNET_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ part_numbers: ["MS21042L3", "AN3-5A"] }),
  });
  console.log(await res.json());
  ```

  ```python Python theme={null}
  import os, requests

  res = requests.post(
      "https://api.skynetparts.com/public/api/v1/b2b/catalog",
      headers={"Authorization": f"Bearer {os.environ['SKYNET_API_KEY']}"},
      json={"part_numbers": ["MS21042L3", "AN3-5A"]},
  )
  print(res.json())
  ```
</RequestExample>

<CodeGroup>
  ```bash Searching by name instead theme={null}
  curl -X POST https://api.skynet-docs.skynetparts.com/public/api/v1/b2b/catalog \
    -H "Authorization: Bearer $SKYNET_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "part_names": ["Self-Locking Nut", "Cotter Pin"] }'
  ```
</CodeGroup>

<CodeGroup>
  ```bash Mixing both theme={null}
  curl -X POST https://api.skynet-docs.skynetparts.com/public/api/v1/b2b/catalog \
    -H "Authorization: Bearer $SKYNET_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "part_numbers": ["MS21042L3"], "part_names": ["Cotter Pin"] }'
  ```
</CodeGroup>

<CodeGroup>
  ```bash In-stock only theme={null}
  curl -X POST https://api.skynet-docs.skynetparts.com/public/api/v1/b2b/catalog \
    -H "Authorization: Bearer $SKYNET_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "part_numbers": ["MS21042L3"], "in_stock": true }'
  ```
</CodeGroup>

<ResponseExample>
  ```json Success theme={null}
  {
    "success": true,
    "found_parts": [
      {
        "part_id": "skynet_part_BWxLDSfV6dFV5o40VwVTV0arE-5dVB7VE22Jd1bb40zYqKv2eI7lRPsBJGk0JleZRO1NI5VQz6qe7KifEy24PQGAL0bZbcE",
        "part_number": "MS21042L3",
        "part_name": "Self-Locking Nut",
        "title": "Self-Locking Nut, MS21042L3",
        "description": "COVER: CUSHION, ASSEMBLY",
        "condition": "NE",
        "unit_of_measure": "EA",
        "available_stock": 87,
        "price": { "amount": "12.40", "currency": "USD" },
        "status": "ACTIVE"
      }
    ],
    "not_found": ["AN3-5A"],
    "summary": { "total_requested": 2, "found": 1, "not_found": 1 }
  }
  ```

  ```json All not found theme={null}
  {
    "success": true,
    "found_parts": [],
    "not_found": ["XYZ-999", "ABC-000"],
    "summary": { "total_requested": 2, "found": 0, "not_found": 2 }
  }
  ```

  ```json Invalid key theme={null}
  {
    "success": false,
    "error": {
      "code": "INVALID_API_KEY",
      "message": "Authorization header missing or malformed."
    }
  }
  ```
</ResponseExample>

## Response fields

<ResponseField name="success" type="boolean">
  `true` for any 200 response including responses where every part landed in `not_found`.
</ResponseField>

<ResponseField name="found_parts" type="object[]">
  One entry per part that matched. Empty array if nothing matched.
</ResponseField>

<ResponseField name="found_parts[].part_id" type="string">
  An opaque ID for the part. Use it when placing an order. Safe to log. Look up the part again if you haven't ordered within an hour.
</ResponseField>

<ResponseField name="found_parts[].part_number" type="string">
  The manufacturer part number.
</ResponseField>

<ResponseField name="found_parts[].part_name" type="string">
  The part name from our catalog metadata.
</ResponseField>

<ResponseField name="found_parts[].description" type="string">
  The part description. Attributes like condition and unit of measure are returned as their own fields below, not inside the description.
</ResponseField>

<ResponseField name="found_parts[].condition" type="string">
  Condition code for the part (e.g. `NE` new, `OH` overhauled, `SV` serviceable).
</ResponseField>

<ResponseField name="found_parts[].unit_of_measure" type="string">
  Unit the part is sold in (e.g. `EA` each).
</ResponseField>

<ResponseField name="found_parts[].title" type="string">
  Human-readable name for the part.
</ResponseField>

<ResponseField name="found_parts[].available_stock" type="integer">
  Units currently on hand.
</ResponseField>

<ResponseField name="found_parts[].price" type="object">
  Our list catalog price for this part. Your account may have a negotiated B2B price that's different the order response always shows your actual `unit_price`. Contains `amount` (string, decimal) and `currency` (string, ISO code).
</ResponseField>

<ResponseField name="found_parts[].status" type="string">
  Lifecycle marker for the part. `ACTIVE` means it can be ordered.
</ResponseField>

<ResponseField name="not_found" type="string[]">
  The exact part numbers or part names from your request that didn't match anything in our catalog. Returned as a successful response (`success=true`), not an error partial matches are normal when sending many parts at once.
</ResponseField>

<ResponseField name="summary" type="object">
  Counts for the request. Contains `total_requested`, `found`, and `not_found` integers.
</ResponseField>

<Note>
  Our catalog price is shown here. Your B2B account may have negotiated lower pricing — your actual unit price is confirmed when you place the order.
</Note>

## Errors

These codes apply to this endpoint:

| Code                | HTTP | Meaning                                                                                           |
| ------------------- | ---- | ------------------------------------------------------------------------------------------------- |
| `VALIDATION_FAILED` | 400  | Body is missing a field or has the wrong type.                                                    |
| `INVALID_API_KEY`   | 401  | Your API key is missing, malformed, or wrong.                                                     |
| `KEY_REVOKED`       | 401  | The key was revoked. Email [info@skynetparts.com](mailto:info@skynetparts.com) for a replacement. |
| `UPSTREAM_ERROR`    | 502  | Catalog lookup failed on our end. Safe to retry.                                                  |

See [Error codes](/reference/errors) for the full list and response shape.
