Gateman
Documentation/Public configuration

Public configuration

display_name: Public configuration
scope: client:read
endpoint:
  method: POST
  path: /config/get
billable: false
environment: required

There is no separate capability_id, ui_capability_key, or operation identifier for this route. client:read is a baseline application scope; Public Configuration is not a separately selectable console capability.

Purpose and authorization

Public Configuration returns a fixed bundle of intentionally non-secret provider configuration for the authenticated application. The values are appropriate for client-facing use, but the Gateman endpoint is not anonymous.

The application MUST authenticate with Contract v1 and MUST have the client:read scope. Gateman resolves configuration using the authenticated immutable app_id; an application cannot select another application's values.

This route does not require secrets:read, a credential-request identifier, or any provider Allow app retrieval setting. Those controls belong to POST /secrets/get. Provider operation scopes such as stripe:use and anti_bot.verify are also independent. Retrieving a publishable or site key does not authorize a provider operation.

Public Configuration returns only eligible public configuration values. Private provider credentials are not available through this endpoint.

Implementation contract

Request

POST /config/get
Content-Type: application/json
X-GM-App: app_example
X-GM-Ts: 1710000000
X-GM-Sig: <Contract-v1-signature>

The request MUST use ordinary signed Contract v1 authentication. The X-GM-Credential-Request-ID header is not required for this route. If supplied, it is accepted but not validated or used by the /config/get authentication or route path; it does not affect signature verification, request processing, or the response. Clients SHOULD ordinarily omit it. An X-GM-Idempotency-Key MAY be supplied and is covered by the Contract v1 signature, but this route has no endpoint-specific idempotency ledger.

The JSON body MUST contain exactly one field:

{
  "environment": "staging"
}

Accepted values are production, staging, and development. The value is required, is normalized by trimming and lowercasing, and is signed as part of the request body. Additional fields are rejected. The caller MUST NOT submit configuration names: this route returns a predefined bundle and is not a list-all or caller-selected credential operation.

The four official Gateman clients can inject the configured environment for environment-aware routes. A direct implementation MUST inject the same field and MUST sign the exact transmitted JSON bytes.

Eligible values

ProviderStored nameResponse field
Stripe productionSTRIPE_PUBLISHABLE_KEYconfig.stripe.publishable_key
Stripe testSTRIPE_PUBLISHABLE_KEY_TESTconfig.stripe.publishable_key
Cloudflare TurnstileTURNSTILE_SITE_KEYconfig.turnstile.site_key
Google reCAPTCHARECAPTCHA_SITE_KEYconfig.recaptcha.site_key

Stripe selection is environment-aware:

Request environmentSelected Stripe value
productionSTRIPE_PUBLISHABLE_KEY
stagingSTRIPE_PUBLISHABLE_KEY_TEST
developmentSTRIPE_PUBLISHABLE_KEY_TEST

There is no fallback between Stripe production and test values. Turnstile and reCAPTCHA site keys use their shared configured values across environments; there are no additional environment-specific site-key names.

The route MUST NOT disclose Stripe secret keys, Stripe webhook secrets, Turnstile secret keys, reCAPTCHA secret keys, private provider credentials, arbitrary custom credentials, or provider configuration metadata.

Successful response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Cache-Control: no-store
{
  "ok": true,
  "config": {
    "stripe": {
      "publishable_key": "pk_test_example"
    },
    "turnstile": {
      "site_key": "0x_example"
    },
    "recaptcha": {
      "site_key": "6Lc_example"
    }
  }
}

The values above are fictitious examples. Values that are not configured or otherwise unavailable are omitted. Empty provider groups are omitted, and an entirely empty configuration is valid:

{
  "ok": true,
  "config": {}
}

Errors

Gateman returns the shared JSON error shape for errors generated by this route:

{
  "ok": false,
  "error": "Invalid JSON"
}

The applicable outcomes are:

ConditionStatus and response error
Missing or invalid authentication, stale timestamp, inactive application, or source-IP rejectionHTTP 401; the authentication error, such as Missing required auth headers, Invalid signature, Unknown app, or Authentication failed.
Missing client:readHTTP 401, Scope not allowed.
Application concurrency limitHTTP 429, app_concurrency_limit_exceeded, with Retry-After: 1.
Application concurrency guard unavailableHTTP 503, app_concurrency_guard_unavailable.
Invalid JSONHTTP 400, Invalid JSON.
Missing environmentHTTP 400, Application environment is required.
Unsupported environmentHTTP 400, Unsupported application environment.
Any field other than environmentHTTP 400, This endpoint accepts only environment.
Public configuration rate-limit dependency unavailableHTTP 503, Public configuration rate limit unavailable.
Dedicated request-frequency limit exceededHTTP 429, public_config_rate_limit_exceeded, with Retry-After.
Public configuration retrieval failureHTTP 500, Public configuration unavailable.

Unavailable individual values do not produce an error; they are omitted from an otherwise successful response. There are no name-selection or excessive-name errors because callers cannot submit names.

Rate limits, accounting, and runtime reuse

Public Configuration is non-billable. It does not create a billable operation reservation or completion record, and it does not consume the monthly billable operation allowance.

The endpoint has a separate fixed-window limit of 10 requests per application per UTC hour. The 11th request in the current UTC-hour window returns:

HTTP/1.1 429 Too Many Requests
Retry-After: <seconds until the UTC-hour window ends>
{
  "ok": false,
  "error": "public_config_rate_limit_exceeded"
}

Authenticated, valid requests reaching this limiter consume its capacity, including requests that return an empty configuration. Rate-limit rejections also increment the limiter's attempt counter under the current implementation. Authentication and request-validation failures that occur before the limiter do not consume its capacity. The shared application concurrency guard also applies.

HTTP response caching and application-managed runtime reuse are different:

  • Gateman returns Cache-Control: no-store, which governs HTTP response caching. Applications MAY retain extracted public configuration values in application-managed runtime state and reuse them as appropriate.
  • An application SHOULD retrieve configuration at initialization or deliberate refresh points rather than repeatedly during ordinary user interactions.
  • An application MAY deliberately persist the values according to its own security and freshness decisions.
  • The application SHOULD reuse the values for later application operations and MUST NOT request them for every page load, user interaction, payment operation, or anti-bot render.
  • A deliberate refresh MUST respect the 10-request-per-UTC-hour limit.
  • A Gateman configuration change is visible on the next uncached retrieval; it does not automatically update values already retained by the application.

Gateman does not provide a universal runtime TTL, freshness guarantee, storage mechanism, or invalidation protocol. The WordPress integration's 12-hour success cache and 15-minute error cache for Stripe publishable-key status are integration-specific choices, not a universal Gateman contract.

Official clients do not automatically retry. A caller implementing retries MUST account for the dedicated request-frequency limit and SHOULD avoid unnecessary repeated retrievals.

Implementation outcome

A correct integration produces these independently assessable outcomes:

  • It authenticates and retrieves the fixed public configuration bundle for its own application.
  • It sends the required environment and receives the correct Stripe production/test publishable key for that environment.
  • It handles missing values and omitted provider groups without assuming that every provider is configured.
  • It keeps private provider credentials out of client-facing configuration.
  • It reuses public configuration in application-managed runtime state instead of requesting it for every user interaction; this is distinct from HTTP response caching.
  • It refreshes deliberately while respecting the request-frequency limit and the HTTP no-store response policy.
  • It handles authentication, concurrency, rate-limit, storage, and validation errors according to their actual HTTP status and error string.
  • It does not treat Public Configuration retrieval as permission to perform a Stripe, Turnstile, reCAPTCHA, or other provider operation.

Implementation instructions for agents

  • SHOULD use an official Gateman client where appropriate. A direct HTTP implementation MUST conform to Contract v1.
  • The integration MUST use authenticated POST /config/get with the client:read scope and a required environment of production, staging, or development.
  • It SHOULD ordinarily omit X-GM-Credential-Request-ID for this route. It is not required and, if supplied, is not validated or used by the /config/get authentication or route path.
  • It MUST NOT submit configuration names or add a caller-controlled field selector; the response bundle is fixed.
  • It MUST use the Stripe production value only for production, and the Stripe test value for staging and development.
  • It MUST treat Turnstile and reCAPTCHA site keys as shared configured values and MUST NOT invent environment-specific site-key names.
  • It MUST handle omitted values and provider groups explicitly.
  • It MUST keep private provider credentials out of this configuration path and MUST NOT grant secrets:read merely to retrieve public values.
  • It MUST NOT require provider Allow app retrieval settings for this route.
  • It SHOULD retrieve configuration at initialization or deliberate refresh points and MAY retain extracted values in application-managed runtime state for reuse. This is distinct from HTTP response caching.
  • It MUST respect the 10-request-per-UTC-hour limit and handle Retry-After on 429 responses.
  • It SHOULD NOT add automatic retries that poll the endpoint repeatedly.
  • It MUST NOT treat a returned public key as provider API authorization.
  • It MUST NOT convert the endpoint into an anonymous configuration service, general credential store, or CDN.

Reusable AGENTS.md block

<!-- gateman:begin capability=public-configuration -->
- Retrieve public provider configuration only through authenticated
  `POST /config/get` using the application's baseline `client:read` scope.
- Supply exactly one required JSON field: `environment`, with value
  `production`, `staging`, or `development`.
- The response is a fixed bundle. Handle omitted Stripe, Turnstile, and
  reCAPTCHA values; do not request names or expect private credentials.
- Stripe uses the production publishable key for `production` and the test
  publishable key for `staging` and `development`. Turnstile and reCAPTCHA
  site keys are shared across environments.
- Gateman remains authenticated even though returned values are public. This
  route does not require `secrets:read` or provider **Allow app retrieval**.
- `X-GM-Credential-Request-ID` is not required for this route. Applications
  SHOULD ordinarily omit it; if supplied, it is not validated or used by the
  `/config/get` authentication or route path.
- Retrieve at initialization or deliberate refresh points rather than
  repeatedly during ordinary user interactions. Applications MAY retain
  extracted values in application-managed runtime state and reuse them.
- Gateman returns `Cache-Control: no-store`, which governs HTTP response
  caching; it does not prohibit application-managed runtime reuse. Do not
  assume a universal local TTL or automatic invalidation guarantee.
- The route is limited to 10 requests per application per UTC hour. Respect
  `Retry-After` on `429` responses and do not add unnecessary automatic
  retries.
- Public Configuration does not authorize Stripe, Turnstile, reCAPTCHA, or
  other provider operations. Keep private provider credentials separate.
- Full reference: https://docs.getgateman.com/public-configuration/
<!-- gateman:end capability=public-configuration -->