HyphaBase

Working with sites

Every request about customers or bookings has to say which site it means. Here's how, and what the errors are telling you.

Sarah's app shows Thursday's bookings. Portland's Thursday, or Salem's? The request has to say.

That's the X-Location-Id header. It carries the id of the site you're asking about, and it goes on every request that touches customers, bookings, invoices or staff.

curl https://api.hyphabase.com/api/modules/clients \
  -u sk_live_xxx: \
  -H "X-Location-Id: 019aff48-a982-70b4-9be8-57eb265122d7"

Setup requests — creating sites, issuing keys, adding staff — don't need it. They happen above the level of any single site.

Telling us which site

Where the id comes from depends on who's asking:

A customer booking online picked a site, or only has one. Your app knows which, and passes it.

A staff member is assigned to sites. Sarah's Portland manager only has Portland, so his session implies it. Sarah has both, so her screen needs a site switcher.

A background job usually loops. Sarah's Sunday email job runs once per site, passing a different id each time. One key can serve every site it's been granted.

// One key, many sites.
for (const siteId of ['019aff48-…', '019aff52-…']) {
  await sendWeeklySchedule(siteId);
}

One database per site

Portland's customers live in a different database from Salem's. Four things follow from that, and they're worth knowing before they surprise you.

Nothing leaks. A bug in a Portland query cannot return Salem's customers. They aren't in the same place to be returned.

Nothing is shared by accident either. Sarah's "Deep clean — 3 bed" service doesn't appear in Salem because she created it in Portland. Things you do want shared — services, products, tax rates — are defined once for the whole app, and each site opts in.

A new site takes a moment. A database has to be created. The site exists immediately, but it's briefly not usable, and requests to it come back 503 until it's ready.

A site can leave. If Sarah sells Salem, everything about Salem goes with it. See handing a site to someone else.

When a request is refused

Four failures, and each says something specific. In roughly the order you'll meet them while wiring things up:

You getIt meansDo this
400You didn't send X-Location-IdAdd the header
403Your key hasn't been given this siteGrant it — see below
404No such site, or it's switched offCheck the id, and which app it belongs to
503The site is still being createdWait a few seconds and retry

A brand-new key can reach nothing

This is the one that catches everyone. Creating a key and giving it access to a site are two separate steps. If a key you just made returns 403, you haven't done the second one yet.

Giving a key access to sites

Done from the key's row in API Keys → Access. Two ways, and they add together:

Tick individual sites. Good when the list is short and stable.

Tick a group. Grant Oregon and the key reaches Portland, Salem, and Eugene when Sarah opens it next year — no second visit needed. This is usually what you want, because otherwise every new site means someone remembering to come back here.

The key access dialog, showing a franchise tree with per-site checkboxes
Ticking a group covers everything inside it, including sites added later.

Access replaces the whole selection rather than adding to it, so what you leave ticked is what the key ends up with.

Finding your site ids

The Locations page lists every site you can see, with its group, region and whether it's ready. Each row has a copy action for the id.

For one site, storing that id in config is fine. For an app that serves several, ask us instead — your key can list what it reaches:

curl https://api.hyphabase.com/api/locations -u sk_live_xxx:
{
  "data": [
    { "id": "019aff48-…", "name": "Portland", "region": "us-west-2", "provisioning_status": "ready" },
    { "id": "019aff52-…", "name": "Salem",    "region": "us-west-2", "provisioning_status": "ready" }
  ]
}

This one endpoint takes no X-Location-Id — it's what you call to find out which id to send. It returns the union of the key's own sites and everything under any group it's been granted, so a site opened next year appears without you changing anything.

A site still being created is listed with provisioning_status: "pending" rather than hidden, because that's the thing you'd poll.

Build your site switcher from this rather than a hardcoded list, and it stays right.

Moving a site between groups

Reorganising is cheap. Each site's row has a Move action; pick the group it should sit under.

The site's data isn't touched. Its customers, bookings and history stay exactly where they are — only where it hangs in the tree changes.

Handing a site to someone else

Sarah sells Salem to a former employee who has her own HyphaBase account.

Neither of them can do this alone — data can't be pushed at you, and it can't be taken from you:

Sarah offers it

From the site's row, Transfer, and the buyer's email address. Nothing moves yet.

The buyer accepts

It appears under Transfers in the buyer's own dashboard, where she picks which of her groups it lands in.

Either side can back out first — Sarah can cancel, the buyer can reject. Once it completes, Salem's customers and history belong to her, and Sarah's keys no longer reach it.

Next

On this page