> For the complete documentation index, see [llms.txt](https://docs.partssource.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.partssource.com/api/cookbooks/search-to-order.md).

# Search to Order

Complete workflow from product search to order placement

This cookbook walks you through the complete workflow to search for products and place an order using the PartsSource API. By the end, you'll understand how data flows from user lookup through order creation.

***

## Overview

Placing an order requires four API calls that build on each other:

| Step | Endpoint             | Purpose                                     |
| ---- | -------------------- | ------------------------------------------- |
| 1    | User/Customer Lookup | Get user profile, companies, addresses      |
| 2    | Catalog Search       | Find products matching your criteria        |
| 3    | Catalog Detail       | Get pricing options and the `priceOptionId` |
| 4    | Create Order         | Place order using the `priceOptionId`       |

{% hint style="warning" %}
**Critical Concept: priceOptionId**

The `priceOptionId` returned from `/catalog/detail` is essentially a **quote** that is valid for **30 days**. You must capture this value from Step 3 and use it when creating an order in Step 4.
{% endhint %}

***

## Prerequisites

* Valid OAuth 2.0 access token (see [Authentication](/api/authentication/overview.md))
* User ID or username for lookup

***

## Step 1: User/Customer Lookup

First, retrieve the user profile to get company information, facility IDs, and shipping/billing addresses needed for ordering.

### Request

```bash
curl -X GET "https://api.partssource.com/customer/api/users/lookup?userId=12345" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json"
```

### Response

```json
{
  "success": true,
  "data": {
    "contactId": 12345,
    "loginUserId": "jsmith",
    "firstName": "John",
    "lastName": "Smith",
    "email": "jsmith@hospital.org",
    "companies": [
      {
        "id": 1001,
        "name": "Memorial Hospital",
        "shippingAddresses": [
          {
            "id": 3001,
            "line1": "123 Medical Center Dr",
            "city": "Chicago",
            "state": "IL",
            "zip": "60601"
          }
        ],
        "billingAddresses": [
          {
            "id": 4001,
            "line1": "123 Medical Center Dr",
            "city": "Chicago",
            "state": "IL",
            "zip": "60601"
          }
        ]
      }
    ]
  }
}
```

### Key Values to Capture

| Field                    | Usage in Later Steps                                |
| ------------------------ | --------------------------------------------------- |
| `contactId`              | `requesterId` for catalog detail and order creation |
| `companies[].id`         | `companyId` for catalog detail and order            |
| `shippingAddresses[].id` | `shippingAddressId` for order                       |
| `billingAddresses[].id`  | `billingAddressId` for order                        |

***

## Step 2: Catalog Search

Search the product catalog using keywords, filters, and pagination.

### Request (Both APIs)

```bash
curl -X POST "https://api.partssource.com/customer/api/catalog/search" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "filters": {
      "query": "ultrasound probe",
      "facets": []
    },
    "pagination": {
      "limit": 50,
      "offset": 0,
      "sortBy": "PartNumber",
      "sortDirection": "Asc"
    },
    "facilityId": 2001,
    "requesterId": 12345
  }'
```

### Response

```json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "CAT-123",
        "partNumber": "PROBE-US-001",
        "displayPartNumber": "PROBE-US-001",
        "description": "High-frequency ultrasound transducer",
        "oem": "GE Healthcare",
        "categories": ["Ultrasound", "Transducers"]
      },
      {
        "id": "CAT-456",
        "partNumber": "PROBE-US-002",
        "displayPartNumber": "PROBE-US-002",
        "description": "Linear array ultrasound probe",
        "oem": "Philips",
        "categories": ["Ultrasound", "Transducers"]
      }
    ],
    "pagination": {
      "total": 24,
      "limit": 50,
      "offset": 0,
      "hasMore": false
    }
  }
}
```

### Key Values to Capture

| Field        | Usage in Later Steps                              |
| ------------ | ------------------------------------------------- |
| `items[].id` | `productId` for catalog detail and order creation |

***

## Step 3: Get Catalog Detail (Critical)

This is the most important step. The catalog detail endpoint returns pricing options, each with a unique `priceOptionId` that acts as a 30-day quote.

### Request

```bash
curl -X POST "https://api.partssource.com/customer/api/catalog/detail" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "CAT-123",
    "facilityId": 2001,
    "requesterId": 12345
  }'
```

### Response

```json
{
  "success": true,
  "data": {
    "product": {
      "id": "CAT-123",
      "partNumber": "PROBE-US-001",
      "title": "High-Frequency Ultrasound Transducer",
      "description": "Compatible with GE Logiq series",
      "manufacturer": "GE Healthcare"
    },
    "options": [
      {
        "priceOptionId": "OPT-ABC123-XYZ",
        "price": 1250.00,
        "condition": "Refurbished",
        "warranty": "12 Months",
        "purchaseChoice": "Buy",
        "customFields": []
      },
      {
        "priceOptionId": "OPT-DEF456-UVW",
        "price": 2500.00,
        "condition": "New OEM",
        "warranty": "24 Months",
        "purchaseChoice": "Buy",
        "customFields": []
      },
      {
        "priceOptionId": "OPT-GHI789-RST",
        "price": 850.00,
        "condition": "Aftermarket",
        "warranty": "6 Months",
        "purchaseChoice": "Buy",
        "customFields": [
          {
            "fieldId": "serial_number",
            "prompt": "Equipment Serial Number",
            "isRequired": true,
            "formatRegex": "^[A-Z0-9]{8,12}$",
            "errorMessage": "Must be 8-12 alphanumeric characters"
          }
        ]
      }
    ]
  }
}
```

### Understanding the Options Array

Each option in the `options` array represents a different purchasing choice:

| Field            | Description                                                 |
| ---------------- | ----------------------------------------------------------- |
| `priceOptionId`  | **Required for order** - The quote ID, valid for 30 days    |
| `price`          | Unit price for this option                                  |
| `condition`      | Product condition (New OEM, Refurbished, Aftermarket, etc.) |
| `warranty`       | Warranty period included                                    |
| `purchaseChoice` | Type of purchase (Buy, Exchange, Loan, etc.)                |
| `customFields`   | Additional fields required by the vendor                    |

{% hint style="warning" %}
**The priceOptionId is your quote**

Think of each `priceOptionId` as a unique quote from a vendor. It locks in:

* The price at the time of lookup
* The specific condition and warranty terms
* The vendor fulfilling the order

This quote expires after **30 days**. If you try to use an expired `priceOptionId`, the order will fail validation.
{% endhint %}

### About customFields

Some pricing options require additional information from the buyer. The `customFields` array defines what data you must provide when creating the order.

| customField Property | Description                        |
| -------------------- | ---------------------------------- |
| `fieldId`            | Identifier to use in order request |
| `prompt`             | User-facing label for the field    |
| `isRequired`         | Whether the field must be provided |
| `formatRegex`        | Validation pattern for the value   |
| `errorMessage`       | Message shown if validation fails  |

***

## Step 4: Create Order

Place the order using the `priceOptionId` from Step 3. Every order request requires an `Idempotency-Key` header.

{% hint style="warning" %}
**Required: Idempotency-Key Header**

Every order creation request MUST include a unique `Idempotency-Key` header (UUID format). This prevents duplicate orders if you need to retry a failed request.

See [Idempotency](/api/core-concepts/idempotency.md) for details.
{% endhint %}

The `shippingMethod` field is required. See [Shipping Methods](/api/domain-concepts/shipping-methods.md) for valid values.

### Request

```bash
curl -X POST "https://api.partssource.com/customer/api/orders" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{
    "requesterId": 12345,
    "userId": 12345,
    "facilityId": 2001,
    "shippingAddressId": 3001,
    "billingAddressId": 4001,
    "shippingMethod": "GROUND",
    "quoteItems": [
      {
        "priceOptionId": "OPT-ABC123-XYZ",
        "productId": "CAT-123",
        "quantity": 1,
        "price": 1250.00
      }
    ],
    "poNumber": "PO-2025-001",
    "notes": "Deliver to loading dock B"
  }'
```

### Response

```json
{
  "success": true,
  "data": {
    "orderNumber": "ORD-2025-12345",
    "createdAt": "2025-01-15T14:35:00.000Z",
    "success": true,
    "eventId": "evt-abc123"
  }
}
```

***

## Ordering Multiple Items

A single order can contain multiple line items by adding more entries to the `quoteItems` array. Each line item needs its own `priceOptionId` obtained from a separate `/catalog/detail` call for that product.

{% hint style="info" %}
**One order, one Idempotency-Key**

Use a single `Idempotency-Key` for the entire multi-item order — not one per line. Retrying the same key with the same body returns the original order rather than creating duplicates.
{% endhint %}

### Before You Submit

* Call `/catalog/detail` once per product and capture the `priceOptionId` for the option you want.
* If a chosen option's catalog detail returned `customFields`, supply the values on that specific line item as `requiredFields`.
* All line items share the order's `shippingAddressId` and `billingAddressId`. Orders that need to split across addresses must be submitted as separate orders.

### Request

```bash
curl -X POST "https://api.partssource.com/customer/api/orders" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
  -d '{
    "requesterId": 12345,
    "userId": 12345,
    "facilityId": 2001,
    "shippingAddressId": 3001,
    "billingAddressId": 4001,
    "shippingMethod": "GROUND",
    "quoteItems": [
      {
        "priceOptionId": "OPT-ABC123-XYZ",
        "productId": "CAT-123",
        "quantity": 1,
        "price": 1250.00
      },
      {
        "priceOptionId": "OPT-DEF456-UVW",
        "productId": "CAT-456",
        "quantity": 2,
        "price": 2500.00
      },
      {
        "priceOptionId": "OPT-GHI789-RST",
        "productId": "CAT-789",
        "quantity": 1,
        "price": 850.00,
        "requiredFields": [
          {
            "fieldId": "22222222-2222-2222-2222-222222222222",
            "value": "GE12345678"
          }
        ]
      }
    ],
    "payment": {
      "paymentMethod": "PO",
      "poNumber": "PO-2025-002"
    },
    "notes": "Combined shipment preferred"
  }'
```

### Validation Notes

* If any `priceOptionId` is expired or invalid, the entire order fails — refresh that line's catalog detail and retry.
* Required field values missing on any line return `422 Unprocessable Entity` with the offending line identified.

***

## Complete Flow Example

{% stepper %}
{% step %}
**Authenticate and get access token**

```bash
curl -X POST "https://auth.partssource.com/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"
```

{% endstep %}

{% step %}
**Look up user to get profile and addresses**

Use the user ID or username to retrieve company information, facility IDs, and addresses.
{% endstep %}

{% step %}
**Search catalog for desired product**

Search using keywords or filters to find the product you want to order.
{% endstep %}

{% step %}
**Get catalog detail with pricing options**

Call `/catalog/detail` with the `productId` from search results. Capture the `priceOptionId` for the option you want.
{% endstep %}

{% step %}
**Create order with priceOptionId**

Submit the order with:

* `priceOptionId` from Step 4
* Address IDs from Step 2
* A unique `Idempotency-Key` header
  {% endstep %}

{% step %}
**Verify order creation**

Check the response for `orderNumber` and `success: true`. Store the order number for tracking.
{% endstep %}
{% endstepper %}

***

## Error Handling

### Common Errors

| Error                      | Cause                                      | Solution                                 |
| -------------------------- | ------------------------------------------ | ---------------------------------------- |
| `400 Bad Request`          | Missing required fields                    | Check required fields for your API       |
| `400 Bad Request`          | Missing Idempotency-Key                    | Add the header with a UUID               |
| `403 Forbidden`            | Tenant mismatch                            | Verify user belongs to the company       |
| `404 Not Found`            | Invalid priceOptionId                      | Get fresh catalog detail before ordering |
| `409 Conflict`             | Idempotency key reused with different body | Use new key for different orders         |
| `422 Unprocessable Entity` | Validation failed                          | Check error details in response          |

### priceOptionId Expired

If your `priceOptionId` is older than 30 days, the order will fail validation. Call `/catalog/detail` again to get a fresh quote with updated pricing.

***

## Next Steps

* [Idempotency](/api/core-concepts/idempotency.md) - Detailed idempotency handling and retry patterns
* [Pagination](/api/core-concepts/pagination.md) - Navigating large catalog result sets
* [Error Handling](/api/core-concepts/error-handling.md) - Complete error reference and handling patterns


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.partssource.com/api/cookbooks/search-to-order.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
