# Base URLs, workspaces, and versions

> Build canonical Hodoflow API URLs and understand how service-account workspace context and surface-specific versions are selected.

Every request goes to the **application host**, not the developer-documentation
host. For Hodoflow Cloud the examples use `https://hodoflow.com`; a self-hosted
deployment substitutes its configured application origin.

```bash
export HODOFLOW_BASE_URL="https://hodoflow.com"
```

Keep the origin free of a trailing slash, then append one complete mount and
path. The public OpenAPI document advertises the application origin while each
operation already contains its full `/api/...` path.

## Canonical mounts

| Surface | Canonical request |
|---|---|
| Token exchange | `POST $HODOFLOW_BASE_URL/api/v1/oauth/token` |
| JSON:API | `$HODOFLOW_BASE_URL/api/json/v1/...` |
| GraphQL | `POST $HODOFLOW_BASE_URL/api/graphql` |
| Webhook ingestion | `POST $HODOFLOW_BASE_URL/api/v1/webhooks/$TRIGGER_TOKEN` |

Legacy token and webhook paths containing an organization domain remain
temporarily available for compatibility but are deprecated. New clients must
use the canonical apex forms above.

## Workspace context comes from the service account

A service account is created while one workspace is selected. That stored
workspace, together with its organization and active run-as member, determines
what API requests can see. Do not send a tenant, organization, or workspace ID
as an authority override. A similarly named resource in another workspace is
not visible through this credential.

Hodoflow validates the signed credential identity, then reloads the service
account, workspace, scopes, and run-as membership for each request. Claims help
locate the tenant record; the mutable database state remains authoritative.

Use separate service accounts when an integration needs separate workspace,
scope, ownership, or revocation boundaries. Never reuse one credential merely
to avoid another token exchange.

## Versions are surface-specific

| Surface | Version identity | How it changes |
|---|---|---|
| JSON:API | `v1` in the path and `x-api-version` response header | Breaking changes require a new mount such as `/api/json/v2` |
| GraphQL | Date version in `x-api-version` and the SDL header | Additive evolution in place; removals follow GraphQL deprecation |
| Token exchange | `/api/v1` route family | OAuth response shape is versioned with the route |
| Webhook ingestion | `/api/v1` route family | Delivery response and authentication contract are versioned with the route |

Do not send a JSON:API version header to change GraphQL behavior. Do not infer a
GraphQL schema date from `v1`. Record the response's `x-api-version` and
`x-request-id` with integration diagnostics.

## Discovery URLs

Use release-matched public artifacts rather than scraping HTML:

- [OpenAPI JSON](/openapi.json) for HTTP operations and schemas;
- [GraphQL SDL](/schema.graphql) for GraphQL names and types;
- [LLM index](/llms.txt) and [full Markdown corpus](/llms-full.txt) for prose;
- `.md` on any guide URL for that page's canonical Markdown.

Continue with [Authentication](/authentication) or read the full
[Versioning and changelog policy](/platform/versioning-changelog).
