Skip to main content

Authentication

ARC has three authentication contracts. Pick one based on the transport you are using; do not mix credentials between them.

CredentialTransportBest forLifetime / rotation
ARC user JWTGraphQL and JWT-protected REST/SSEAn integration acting as a signed-in ARC userAccess token: 1 hour. Refresh token: 7 days and rotated on use.
Tenant API key/api/service/* REST routesServer-to-server catalog, customer and document reads, quotes, orders, and product importsCreated per organization; optional expiry and IP allowlist; full key shown once.
MCP OAuth token/mcpAI agents and MCP clientsAccess token: 1 hour. Refresh tokens rotate and are bound to the MCP origin.

Tenant API keys: machine integrations​

An organization administrator or manager with API access creates a key in Settings → API keys. The API key feature is plan-gated; ask your Growmax account manager if the setting is unavailable.

A key has:

  • a gm_live_ prefix followed by 48 hexadecimal characters;
  • a tenant scope — one key can access only the organization that created it;
  • READ_ONLY or READ_WRITE scope (READ_ONLY is the default);
  • optional expiry (expiresAt or expiresInDays, 1–3650 days);
  • optional IPv4, IPv6, or CIDR allowlist;
  • a rateLimit: requests per minute, an integer from 1 to 10000, 100 by default, enforced per key;
  • a friendly name and masked prefix for inventory and rotation.

The raw key is returned only by createApiKey at creation time. ARC stores a hash, not the raw credential. If it is lost, revoke it and create a replacement.

Send an API key​

curl --fail-with-body \
--header "Authorization: Bearer $ARC_API_KEY" \
"$ARC_API_URL/api/service/payment-terms"

The organization is taken from the validated key. There is no supported organizationId header, query parameter, or body field that changes the tenant.

READ_ONLY keys can call every read route: the catalog, stock, reference lists, customers, sales-order and quote status, and import status and preview. Creating quotes, creating orders, and mutating imports require READ_WRITE. See Service REST API.

Rotate safely​

  1. Create a replacement key first.
  2. Deploy the replacement to your secret manager.
  3. Verify a read request and one non-destructive workflow in the target tenant.
  4. Revoke the old key in Settings → API keys.
  5. Remove the old value from CI, logs, local shells, and incident notes.

The key's rateLimit is enforced: every request made with the key counts against it, in a fixed one-minute window. Over the limit, ARC answers 429 with code API_KEY_RATE_LIMITED and a Retry-After header. The global per-IP throttle also still applies. A key cannot be edited, so to change its limit, create a replacement key and rotate. Build bounded concurrency, backoff, and retry handling into the integration, and agree higher throughput with Growmax before a large migration. See Rate limits and request limits.

User JWTs: GraphQL and user-scoped REST​

GraphQL login is a public mutation that resolves the tenant from the request's subdomain (or the tenant host) and returns an access/refresh pair. The access token is sent as a normal Bearer token.

mutation Login($input: LoginInput!) {
login(loginInput: $input) {
accessToken
refreshToken
expiresIn
tokenType
organizationId
user { id email firstName lastName }
}
}
{
"input": {
"email": "developer@example.com",
"password": "<password>",
"subdomain": "<tenant-subdomain>"
}
}
Authorization: Bearer <accessToken>
Content-Type: application/json

Access tokens expire after one hour. Refresh before expiry with the refreshToken mutation and replace both stored tokens because refresh tokens rotate:

mutation Refresh($input: RefreshTokenInput!) {
refreshToken(refreshTokenInput: $input) {
accessToken
refreshToken
expiresIn
tokenType
}
}

JWT access is permission-driven. A valid login does not grant every resolver: the user's current ARC permissions are loaded and checked on each authenticated operation. This is useful for staff-facing applications, but a long-lived machine integration should normally use a tenant API key and the documented service routes instead of automating a human password.

MCP OAuth​

MCP clients do not use API keys or ARC JWTs directly. They discover OAuth metadata from the host, use authorization code + PKCE (S256), show the seller a consent page, and receive a token bound to one user, one organization, and the exact /mcp origin.

See MCP for the handshake, refresh/revocation behavior, tool filtering, and the propose → human approval → apply write contract.

Credential safety​

  • Keep all credentials in a server-side secret manager.
  • Never put an API key, JWT, refresh token, or MCP token in browser JavaScript, a mobile binary, a Git repository, an issue, or a request log.
  • Do not send organizationId from a client and do not trust an organization id returned by a caller's body when selecting a tenant.
  • Treat a 401 as an authentication or credential configuration problem; do not retry it indefinitely.
  • Revoke a compromised key immediately. Revoking a key (revokeApiKey) takes effect on the next request made with it.

Next: Make your first GraphQL request.