JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 20
  • Score
    100M100P100Q83342F
  • License MIT

TypeScript SDK for the Cohost API — auto-generated from OpenAPI spec

Package Exports

  • cohost-client

Readme

cohost-client

TypeScript SDK for the Cohost External API. Fully typed API client auto-generated from the OpenAPI spec using Orval.

Features

  • Fully typed request/response types generated from OpenAPI spec
  • Works in both browser and Node.js (18+)
  • Two auth modes: API Key (backend) and JWT Bearer (frontend)
  • Self-updating — regenerate types and functions with npm run generate
  • Zero runtime dependencies (uses native fetch)

Installation

npm install cohost-client

The Auth Architecture

The Cohost API uses two distinct auth mechanisms:

Endpoint group Auth required Who calls it
/api/v1/external/* X-API-Key header Your server only
/api/v1/checkout/*, /api/v1/bookings/my, /api/v1/auth/me Bearer <JWT> Your frontend

Never expose your API key in client-side code. Environment variables prefixed with NEXT_PUBLIC_, VITE_, REACT_APP_, etc. get bundled into your JS and are readable by anyone in DevTools. Keep the key in unprefixed server-only env vars.

The intended flow:

Browser                  Your Server               Cohost API
  │                           │                        │
  │── POST /auth/login ───────►│                        │
  │                           │── customerLogin...() ─►│  (X-API-Key)
  │                           │◄── { access_token } ───│
  │◄── { access_token } ──────│                        │
  │                           │                        │
  │  setBearerToken(token)    │                        │
  │── getListings...() ───────────────────────────────►│  (Bearer JWT)

Quick Start

Server-side (API key)

// lib/cohost-server.ts — never import from a 'use client' component
import {
  configureClient,
  getListingsApiV1ExternalListingsGet,
} from "cohost-client";

configureClient({
  apiKey: process.env.COHOST_API_KEY, // no NEXT_PUBLIC_ prefix
});

export async function fetchListings() {
  const res = await getListingsApiV1ExternalListingsGet();
  return res.data;
}

After login (JWT)

import {
  configureClient,
  customerLoginApiV1ExternalCustomersLoginPost,
  setBearerToken,
  getListingsApiV1ExternalListingsGet,
} from "cohost-client";

configureClient({ apiKey: "cohost_api_xxx" });

const login = await customerLoginApiV1ExternalCustomersLoginPost({
  email: "user@example.com",
  password: "…",
});
setBearerToken(login.data.access_token);

const listings = await getListingsApiV1ExternalListingsGet();

Configuration

configureClient(options)

Call once at startup (or per request in server code). All generated functions use this global config.

import { configureClient } from "cohost-client";

configureClient({
  baseUrl: "https://v2-staging.api.cohost.ai",
  apiKey: process.env.COHOST_API_KEY,
  bearerToken: "eyJhbGciOi...", // optional pre-set JWT
  customFetch: myFetch, // optional — see below
  onRequest: (url, init) => init,
  onResponseError: (response, url) => {},
});

Auth headers

  • If apiKey is set → every request gets X-API-Key (unless already present).
  • If bearerToken is set (via configureClient or setBearerToken) → Authorization: Bearer … is added.

JWT persistence (localStorage, cookies, etc.) is your responsibility — read the token and call setBearerToken when your app loads or after login.

setBearerToken / setApiKey

Update credentials at runtime without re-calling configureClient.

Custom fetch implementation

By default the SDK uses the global fetch. Pass customFetch to replace it with any compatible transport — useful for Angular, testing, or custom middleware.

Angular (HttpClient)

Angular's HttpClient returns Observables rather than Promise<Response>, so wrap it to match the fetch signature:

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { firstValueFrom } from "rxjs";
import { configureClient } from "cohost-client";

@Injectable({ providedIn: "root" })
export class CohostService {
  constructor(private http: HttpClient) {
    configureClient({
      apiKey: "cohost_api_xxx",
      customFetch: (url, init) =>
        firstValueFrom(
          this.http.request(
            new Request(url, init)
          )
        ),
    });
  }
}

Testing (mock fetch)

import { configureClient } from "cohost-client";

configureClient({
  customFetch: async (url, init) => {
    return new Response(JSON.stringify({ data: "mocked" }), {
      status: 200,
      headers: { "Content-Type": "application/json" },
    });
  },
});

Node.js (custom agent, proxies, etc.)

import { configureClient } from "cohost-client";
import { fetch, Agent } from "undici";

configureClient({
  customFetch: (url, init) =>
    fetch(url, {
      ...init,
      dispatcher: new Agent({ connect: { timeout: 10_000 } }),
    }) as Promise<Response>,
});

Error Handling

Non-2xx responses throw CohostApiError with status, statusText, body, and url:

import {
  CohostApiError,
  listCustomersApiV1ExternalCustomersGet,
} from "cohost-client";

try {
  await listCustomersApiV1ExternalCustomersGet();
} catch (error) {
  if (error instanceof CohostApiError) {
    console.error(error.status, error.body);
  }
}

Successful responses are { data, status, headers } (Orval fetch client shape). Inspect status on the returned object if you need to branch on 200 vs 201, etc.

API Reference (generated)

Function names follow the OpenAPI operationIds. Import from cohost-client — they are grouped in modules by tag: customers, bookings, listings, reference.

Customers (./generated/customers re-exported)

Function Description
customerLoginApiV1ExternalCustomersLoginPost Customer login
registerCustomerApiV1ExternalCustomersRegisterPost Register customer
listCustomersApiV1ExternalCustomersGet List customers
getCustomerApiV1ExternalCustomersUserIdGet Get customer
updateCustomerApiV1ExternalCustomersUserIdPatch Update customer
removeCustomerFromTeamApiV1ExternalCustomersUserIdTeamsTeamIdDelete Remove from team
resendVerificationApiV1ExternalCustomersUserIdResendVerificationPost Resend verification
checkCustomerEmailVerificationApiV1ExternalCustomersUserIdEmailVerificationGet Email verification status

Listings

Function Description
getListingsApiV1ExternalListingsGet List listings
getListingDetailApiV1ExternalListingsListingIdGet Detail by ID
getListingDetailBySlugApiV1ExternalListingsSlugSlugGet Detail by slug
getListingAvailabilityApiV1ExternalListingsListingIdAvailabilityGet Availability by ID
getListingAvailabilityBySlugApiV1ExternalListingsSlugSlugAvailabilityGet Availability by slug

Bookings

Function Description
previewExternalBookingApiV1ExternalBookingsPreviewPost Preview pricing
createExternalBookingApiV1ExternalBookingsPost Create booking
listExternalBookingsApiV1ExternalBookingsGet List bookings
getExternalBookingDetailApiV1ExternalBookingsBookingIdGet Booking detail

Reference

Function Description
getCatalogsApiV1ExternalCatalogsGet Catalogs
getAmenitiesApiV1ExternalAmenitiesGet Amenities
listCountriesApiV1ExternalLocationsCountriesGet Countries
listProvincesApiV1ExternalLocationsCountryCodeProvincesGet Provinces

Request/response types live under export * from "./generated/schemas" — import named types from cohost-client (e.g. CustomerLoginRequest).

Updating the SDK

When the Cohost API spec changes, regenerate the client:

# Fetch latest spec and regenerate all types + functions
npm run generate

# Or step by step:
npm run generate:fetch   # Download latest OpenAPI spec
npm run generate:clean   # Remove old generated code
npm run generate:orval   # Regenerate TypeScript client

# Then rebuild
npm run build:only

The full npm run build command runs the entire pipeline: fetch spec → generate code → bundle.

CI/CD Auto-Update

You can set up a scheduled CI job to auto-detect API changes:

# .github/workflows/update-sdk.yml
name: Update SDK
on:
  schedule:
    - cron: "0 */6 * * *"  # Every 6 hours
  workflow_dispatch:

jobs:
  update:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm ci
      - run: npm run generate
      - run: npm run build:only
      - uses: peter-evans/create-pull-request@v6
        with:
          title: "chore: update SDK from latest API spec"
          commit-message: "chore: regenerate SDK from latest OpenAPI spec"
          branch: auto-update-sdk

Development

# Install dependencies
npm install

# Generate client from OpenAPI spec
npm run generate

# Build library
npm run build:only

# Full pipeline (generate + build)
npm run build

# Type check
npm run typecheck

# Watch mode
npm run dev

Architecture

src/
├── fetcher.ts           # configureClient + mutator used by Orval-generated functions
├── index.ts             # Barrel exports
└── generated/           # Auto-generated by Orval (do not edit)
    ├── customers/
    ├── bookings/
    ├── listings/
    ├── reference/
    └── schemas/

Compatibility

Runtime environments

The SDK uses only standard Web APIs (fetch, Headers, Request, Response) with no runtime dependencies, so it runs anywhere these are natively available:

Environment Min version Notes
Node.js 18.0.0+ Native fetch added in Node 18
Bun Any stable Native fetch supported
Deno Any stable Native fetch supported
Cloudflare Workers Fully supported
Vercel Edge / Netlify Edge Fully supported
Modern browsers All evergreen browsers

Node 16 and below are not supported — they do not have native fetch.

Module formats

The package ships both formats so it works regardless of your project setup:

Format File Use case
ESM dist/index.mjs import in modern projects, bundlers, Vite, Next.js
CJS dist/index.cjs require() in older Node.js setups

TypeScript declarations are included for both formats (.d.mts / .d.cts).

Frontend frameworks

The SDK is framework-agnostic and works with any frontend framework out of the box:

Framework Works Notes
React / Next.js / Remix Wrap calls in @tanstack/react-query or swr for loading/caching
Vue / Nuxt Wrap in a composable or use vue-query
Svelte / SvelteKit Use in load functions or stores
Solid.js Use with createResource
Astro Use in .astro frontmatter or API routes
Angular Wrap in an @Injectable service; plug in HttpClient via customFetch
Plain JS/TS No framework required

The SDK does not ship framework-specific hooks or bindings. This keeps it lean and lets you integrate it with whichever data-fetching layer your app already uses.

TypeScript

TypeScript 5.0+ is recommended. The generated types use modern TypeScript features. Older versions may work but are not tested.

License

MIT