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

# AI integration guide

> A precise implementation guide for people and AI coding agents using the HFSAA Public API.

This guide is a compact implementation recipe for applications that display HFSAA-certified locations. It applies equally to human developers and AI coding agents.

## Non-negotiable rules

1. Use the production base URL: `https://api.hfsaa.org` and send a production API key as a Bearer token.
2. Keep the API key in a server-side secret; never expose it in browser or mobile application code.
3. Cache API data for no more than one hour, then revalidate or fetch fresh data.
4. Treat the documented API response as the complete HFSAA data contract. Do not infer, scrape, or expose additional fields.
5. When your product states or implies HFSAA certification, identify HFSAA and give users reasonable access to that location's `verification_url`.
6. Do not construct or alter `verification_url` values. Use the exact URL returned by the API.

## Fetch locations

Use one endpoint for restaurants, meat markets, and dining halls. Select a category with the `type` query parameter when needed.

```ts theme={null}
const API_BASE_URL = "https://api.hfsaa.org";
const HFSAA_API_KEY = process.env.HFSAA_API_KEY;

type LocationType = "restaurant" | "meat_market" | "dining_hall";

async function listLocations(options: {
  type?: LocationType;
  state?: string;
  city?: string;
  limit?: number;
  cursor?: string;
} = {}) {
  const params = new URLSearchParams();

  if (options.type) params.set("type", options.type);
  if (options.state) params.set("state", options.state);
  if (options.city) params.set("city", options.city);
  if (options.limit) params.set("limit", String(options.limit));
  if (options.cursor) params.set("cursor", options.cursor);

  const response = await fetch(
    `${API_BASE_URL}/v1/locations?${params.toString()}`,
    {
      headers: {
        Accept: "application/json",
        Authorization: `Bearer ${HFSAA_API_KEY}`
      }
    }
  );

  const body = await response.json();

  if (!response.ok) {
    throw new Error(body.error?.message ?? "HFSAA API request failed");
  }

  return body;
}
```

For example:

```bash theme={null}
curl "https://api.hfsaa.org/v1/locations?type=dining_hall&limit=1" \
  -H "Authorization: Bearer $HFSAA_API_KEY"
```

A successful response has this shape:

```json theme={null}
{
  "dataset_version": "2ec27a5c-79c4-4fd3-9fd5-95eb2f1fc354",
  "data": [
    {
      "id": "50796ba5-9523-4c7f-a74a-465b4d03f0e1",
      "type": "dining_hall",
      "name": "NYU Jasper H. Kane Dining Hall",
      "verification_url": "https://hfsaa-public-locator.pages.dev/?certificate_id=HFSAA-R-9C3E205780",
      "certification_status": "certified",
      "chapter_name": "New York",
      "address": "6 MetroTech Center",
      "city": "Brooklyn",
      "state": "NY",
      "zip_code": "11201",
      "cuisine_type": null,
      "google_place_id": "ChIJ85aDTUpawokRxyqHxTnodLI"
    }
  ],
  "pagination": {
    "limit": 1,
    "next_cursor": "eyJpZCI6IjUwNzk2YmE1LTk1MjMtNGM3Zi1hNzRhLTQ2NWI0ZDAzZjBlMSJ9"
  }
}
```

## Render verification and attribution

When you state or imply that a location is certified or halal verified by HFSAA, identify HFSAA and provide reasonable access to the exact returned `verification_url`. There is no required wording or placement.

```tsx theme={null}
function HfsaaLocationCard({ location }: { location: Location }) {
  return (
    <article>
      <h2>{location.name}</h2>
      {location.city && location.state && (
        <p>{location.city}, {location.state}</p>
      )}

      <p>
        Certified by <a href={location.verification_url}>HFSAA</a>
      </p>
    </article>
  );
}
```

The link may instead be associated with an HFSAA name, badge, **Learn more** link, or another clearly related details element. In a digital product it must be clickable. Offline material may print the URL or use a QR code. Do not substitute a generic HFSAA link for the location-specific `verification_url`, and do not suggest that HFSAA endorses your application.

## Handle nullable directory fields

`chapter_name`, `address`, `city`, `state`, `zip_code`, `cuisine_type`, and `google_place_id` may each be `null`. Do not assume that address or chapter information is present. Omit or adapt UI elements that depend on unavailable values.

## Paginate correctly

Responses include `pagination.next_cursor`.

* If it is a string, pass that exact value as `cursor` in the next request.
* If it is `null`, there are no further results.
* Keep the same filters while moving through pages.
* Treat cursors as opaque values. Do not decode, modify, or generate them.
* Every page repeats the same immutable `dataset_version`, even if a newer snapshot is published while you paginate.
* Superseded versions remain available for at least seven days. If a cursor returns HTTP `410`, restart without that cursor.
* `limit` must be an integer from 1 to 100.

```ts theme={null}
const firstPage = await listLocations({ type: "restaurant", limit: 25 });

const secondPage = firstPage.pagination.next_cursor
  ? await listLocations({
      type: "restaurant",
      limit: 25,
      cursor: firstPage.pagination.next_cursor
    })
  : null;
```

## Handle validation errors

Correct invalid requests rather than retrying them unchanged. For example, `limit=0` returns HTTP `400`:

```json theme={null}
{
  "error": {
    "code": "invalid_parameter",
    "message": "limit must be an integer between 1 and 100."
  }
}
```

An unknown location ID returns HTTP `404`. Rate and monthly limits are assigned per API key; HTTP `429` includes `Retry-After`. Retry `429`, `500`, `502`, `503`, and `504` with bounded exponential backoff and jitter, honoring `Retry-After` when present. Do not retry invalid `400` requests unchanged.

## Download a reproducible snapshot

Fetch `GET /v1/dataset` before downloading a complete dataset. Its response includes:

* an opaque `dataset_version`
* the UTC `generated_at` time
* the exact `location_count`
* a SHA-256 checksum
* a version-specific `download_url`

The checksum covers the exact bytes returned by `download_url`. Use that version-specific URL when storing or redistributing a snapshot.

The one-hour caching limit still applies to version-specific downloads. Revalidate or fetch a fresh copy after one hour even when the same immutable version remains available from the API.

## Google Place IDs

`google_place_id` is optional and is only an identifier. The HFSAA API does not return Google photos, hours, maps, ratings, or other Google content.

If you enrich a listing through Google Places, use your own Google Maps Platform project, credentials, billing, attribution, and policy compliance. HFSAA attribution remains required for the HFSAA data displayed alongside that enrichment.

## Implementation checklist

* [ ] Fetch only from `https://api.hfsaa.org`.
* [ ] Send the production API key as a Bearer token from server-side code only.
* [ ] Revalidate or refresh all cached API data within one hour.
* [ ] Filter location listings with `type`, `state`, `city`, `zip_code`, `chapter`, or `q` as needed.
* [ ] Follow `next_cursor` for additional pages.
* [ ] Confirm every page in a pagination sequence has the same `dataset_version`.
* [ ] Restart pagination if an expired cursor returns HTTP `410`.
* [ ] Honor `Retry-After` and use bounded backoff with jitter for retryable responses.
* [ ] Verify complete downloads against the SHA-256 checksum from `GET /v1/dataset`.
* [ ] When claiming HFSAA certification, identify HFSAA and make the exact `verification_url` reasonably accessible.
* [ ] Handle nullable chapter, address, cuisine, and Google Place ID fields.
* [ ] Keep Google Places enrichment separate and use your own provider credentials.
* [ ] Refer to the [API Reference](/api-reference) for the authoritative endpoint and field definitions.
