Farther ShoreDocs
Go to Farther Shore
Understand gateway behavior
Consuming the API
Monetary admission
Usage limits
Gate API routes by plan
OutcomePrerequisitesVerify in previewCommon failuresRecoverAgent prompt
Diagnose a denied request
Response & deny codes
gateway HTTP contracts
Status
Docs/Cookbook/Gate API routes by plan

Gate API routes by plan

Grant route refs to selected plans and verify denial at the edge.

Use direct route grants when only selected plans should reach an operation. The gateway, not the UI, is the authority.

Outcome

Each plan receives exactly the API operations it grants by ref.

Prerequisites

  • Existing plans and a preview environment
  • Stable route paths or explicit action ids
  • Test subscribers on both an allowed and denied plan
ts
import * as fs from "@farthershore/business";

const requests = fs.requests();
const api = fs.backend("api", {
  transport: { mode: "direct" },
  meters: [requests],
  default: true,
});
const listJobs = fs.route("/v1/jobs", {
  get: { backend: api, costs: [requests.fixed(1)] },
});
const createJob = fs.route("/v1/jobs/create", {
  post: { backend: api, costs: [requests.fixed(1)] },
});
const deleteJob = fs.route("/v1/jobs/{id}", {
  delete: { backend: api, costs: [requests.fixed(1)] },
});
const managedJobs = fs.group("managed-jobs", [listJobs, createJob, deleteJob]);

fs.plan("starter", {
  kind: fs.plan.kind.free,
  grants: [listJobs],
  limits: [requests.perMinute(60)],
});

fs.plan("pro", {
  kind: fs.plan.kind.flat,
  price: fs.money.usd(29).monthly(),
  grants: [managedJobs],
  limits: [requests.perMinute(600)],
});

export default fs.business();

Starter can list jobs but cannot mutate them. Pro grants the group and can use all three operations.

Verify in preview

After the push, wait for route-grants-preview to appear in env list before creating the backend row. If automatic branch-prefix creation did not occur, create the preview explicitly first:

bash
farthershore build --format json
farthershore validate --format json
git push -u origin HEAD:env/route-grants-preview
farthershore env list <business> --format json
farthershore backend create <business> --env route-grants-preview \
  --name "Preview API" --slug api --transport direct \
  --idempotency-key <persisted-backend-create-attempt-key> \
  --origin-url https://preview-api.example.com --default --format json
farthershore backend list <business> --format json

Filter the structured backend list by the preview's environment id.

Test one subscriber on each plan:

  • Starter: GET /v1/jobs succeeds.
  • Starter: POST /v1/jobs/create and DELETE /v1/jobs/{id} return the stable authorization denial.
  • Pro: every declared operation succeeds when the request is otherwise valid.

Client-side hiding is optional presentation. Never treat it as authorization; the route grant is enforced at the gateway.

Common failures

  • A plan has too much access: grant the narrow route ref instead of the group.
  • A grant has no effect: reuse the exact ref returned by fs.route().
  • The build rejects a ref: do not forge refs or reuse a ref from another compile.

Recover

Change the affected plan's grants, rebuild, and publish a forward contract revision. Keep stable route paths and action ids when possible.

Agent prompt

Grant these API operations by plan using direct fs.route() or fs.group() refs. Build and validate, verify both allowed and denied subscribers in preview, and do not publish production.

PreviousUsage limitsNextDiagnose a denied request

On this page

OutcomePrerequisitesVerify in previewCommon failuresRecoverAgent prompt