Skip to main content
No SDK installation required — use the built-in fetch API.

Quick start

const BHUMI_API_KEY = process.env.BHUMI_API_KEY!;
const BASE_URL = "https://api.bhumifarms.co";

async function bhumiGet<T = any>(
  endpoint: string,
  params?: Record<string, string | number>
): Promise<T> {
  const url = new URL(`${BASE_URL}${endpoint}`);
  if (params) {
    Object.entries(params).forEach(([k, v]) =>
      url.searchParams.set(k, String(v))
    );
  }

  const res = await fetch(url, {
    headers: { "X-API-Key": BHUMI_API_KEY },
  });

  if (!res.ok) {
    const error = await res.json();
    throw new Error(`${error.error.code}: ${error.error.message}`);
  }

  return res.json();
}

// Search farms near Portland
const { data, meta } = await bhumiGet("/v1/search", {
  lat: 45.52,
  lng: -122.68,
  radius: 25,
  products: "raw milk,eggs",
});

data.forEach((farm) => {
  console.log(`${farm.name}${farm.distance_mi}mi`);
});

With Next.js (server component)

// app/farms/page.tsx
export default async function FarmsPage() {
  const res = await fetch(
    "https://api.bhumifarms.co/v1/search?lat=45.52&lng=-122.68&radius=25",
    {
      headers: { "X-API-Key": process.env.BHUMI_API_KEY! },
      next: { revalidate: 300 }, // Cache for 5 minutes
    }
  );

  const { data } = await res.json();

  return (
    <ul>
      {data.map((farm) => (
        <li key={farm.id}>{farm.name} — {farm.distance_mi}mi</li>
      ))}
    </ul>
  );
}

Pagination helper

async function getAllFarms(state: string) {
  const farms = [];
  let page = 1;
  let hasMore = true;

  while (hasMore) {
    const result = await bhumiGet("/v1/farms", {
      state,
      page,
      per_page: 100,
    });
    farms.push(...result.data);
    hasMore = result.meta.has_more;
    page++;
  }

  return farms;
}

Error handling

try {
  const farm = await bhumiGet("/v1/farms/invalid-id");
} catch (err) {
  console.error(err.message);
  // NOT_FOUND: Farm not found.
}