# Search Fulfillments
> Source: /api-reference/partner/fulfillments/search
> Search fulfillments with rich filtering and enriched response
> Endpoint: GET /partner/fulfillments/search

## Overview [#overview]

Enriched fulfillment search. Returns nested member, offer, reservation, and property summaries in a single response — purpose-built for fulfillment management UIs that need to display all context without additional lookups.

Unlike `GET /partner/fulfillments`, this endpoint:
- Returns enriched sub-objects (member name, offer details, property info)
- Supports full-text search across offer name, verification code, and member name
- Supports date-range filters across claimed/expired/fulfilled timestamps
- Supports redemption type filtering (defaults to excluding `static` offers)
- Includes `operatorNotes`, `howToRedeem`, and `staffInstructions` from the offer

## Authentication [#authentication]

Requires a partner API key with the `partner:fulfillments:read` scope, sent as `X-API-Key`.

## Query Parameters [#query-parameters]

<ParamField query="q" type="string">
  Full-text search across offer name, verification code, and member name. Minimum 2 characters.
</ParamField>

<ParamField query="status" type="string">
  Comma-separated statuses: `claimed`, `fulfilled`, `pending_approval`, `approved`, `rejected`, `expired`
</ParamField>

<ParamField query="redemptionType" type="string">
  Comma-separated redemption types: `direct`, `requireApproval`, `externalCode`, `static`, `propertyInternal`, `journeyInternal`, `user`, `notification`, `giveaway`.

  **Default behavior when omitted**: excludes `static` only — all other types are returned. Pass an explicit list to restrict to specific types.
</ParamField>

<ParamField query="propertyId" type="number">
  Filter by internal property ID
</ParamField>

<ParamField query="organizationId" type="string">
  External org ID (HXP UUID or WorkOS org ID). Required for superadmin keys querying a specific org; ignored for org-scoped keys.
</ParamField>

<ParamField query="claimedAfter" type="string">
  ISO 8601 — include fulfillments claimed on or after this date
</ParamField>

<ParamField query="claimedBefore" type="string">
  ISO 8601 — include fulfillments claimed on or before this date
</ParamField>

<ParamField query="expiresAfter" type="string">
  ISO 8601 — include fulfillments expiring on or after this date
</ParamField>

<ParamField query="expiresBefore" type="string">
  ISO 8601 — include fulfillments expiring on or before this date
</ParamField>

<ParamField query="fulfilledAfter" type="string">
  ISO 8601 — include fulfillments completed on or after this date
</ParamField>

<ParamField query="fulfilledBefore" type="string">
  ISO 8601 — include fulfillments completed on or before this date
</ParamField>

<ParamField query="offset" type="number" default="0">
  Pagination offset
</ParamField>

<ParamField query="limit" type="number" default="20">
  Results per page (max 100)
</ParamField>

## Response [#response]

<ResponseField name="items" type="array" required>
  Enriched fulfillment records
  <Expandable title="item fields">
    <ResponseField name="id" type="string">Fulfillment ID</ResponseField>
    <ResponseField name="status" type="string">`claimed` | `fulfilled` | `pending_approval` | `approved` | `rejected` | `expired`</ResponseField>
    <ResponseField name="approvalStatus" type="string | null">Current approval workflow state</ResponseField>
    <ResponseField name="redemptionType" type="string">How this fulfillment is redeemed</ResponseField>
    <ResponseField name="verificationCode" type="string | null">Staff verification code</ResponseField>
    <ResponseField name="qrCodeUrl" type="string | null">QR code image URL</ResponseField>
    <ResponseField name="pointsCharged" type="number | null">Points deducted from member</ResponseField>
    <ResponseField name="retailValue" type="number | null">USD retail value of the item</ResponseField>
    <ResponseField name="claimedAt" type="string | null">ISO 8601 timestamp</ResponseField>
    <ResponseField name="fulfilledAt" type="string | null">ISO 8601 timestamp</ResponseField>
    <ResponseField name="expiresAt" type="string | null">ISO 8601 timestamp</ResponseField>
    <ResponseField name="canApprove" type="boolean">Whether the calling key can approve this fulfillment</ResponseField>
    <ResponseField name="canFulfill" type="boolean">Whether the calling key can mark this as fulfilled</ResponseField>
    <ResponseField name="operatorNotes" type="string | null">Internal notes visible to property staff</ResponseField>
    <ResponseField name="member" type="object">
      `{ firstName, lastName, externalMemberId }`
    </ResponseField>
    <ResponseField name="offer" type="object | null">
      `{ name, publicName, imageThumbUrl, categorySlug, categoryName, fulfillmentType, requiresApproval, howToRedeem, staffInstructions }`
    </ResponseField>
    <ResponseField name="reservation" type="object | null">
      `{ externalId, checkIn, checkOut }`
    </ResponseField>
    <ResponseField name="property" type="object">
      `{ id, externalId, name }`
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="total" type="number" required>Total matching fulfillments</ResponseField>
<ResponseField name="offset" type="number" required>Current offset</ResponseField>
<ResponseField name="limit" type="number" required>Page size used</ResponseField>

<RequestExample>

```bash Search pending approvals
curl "https://api-prd.cf.journey.com/v1/partner/fulfillments/search?status=pending_approval&limit=20" \
  -H "X-API-Key: jny_xxxx"
```

```bash Search by member name this week
curl "https://api-prd.cf.journey.com/v1/partner/fulfillments/search?q=johnson&claimedAfter=2026-05-19&status=claimed,fulfilled" \
  -H "X-API-Key: jny_xxxx"
```

```typescript TypeScript
const results = await fetch(
  'https://api-prd.cf.journey.com/v1/partner/fulfillments/search?' +
  new URLSearchParams({
    status: 'pending_approval,claimed',
    redemptionType: 'requireApproval,direct',
    limit: '50'
  }),
  { headers: { 'X-API-Key': apiKey } }
).then(r => r.json());

results.items.forEach(item => {
  console.log(`${item.member.firstName} ${item.member.lastName}`);
  console.log(`Offer: ${item.offer?.name} — ${item.status}`);
  if (item.offer?.staffInstructions) {
    console.log(`Instructions: ${item.offer.staffInstructions}`);
  }
});
```

</RequestExample>

## Bruno [#bruno]

`bruno/Partner/Fulfillments/Search Fulfillments.bru`
