Machine-to-Machine Quickstart
Use the OAuth 2.0 client credentials flow when software acts as itself and no user is present. This applies to backend services, workers, scheduled jobs, agents, and MCP servers.
1. Register Both Sides
In Guardhouse:
- Register the target API resource and its audience.
- Create the API scopes the service may request.
- Create a confidential backend/service client.
- Allow that client to request only the required resource and scopes.
- Copy the client ID and client secret once, then store the secret in server-side secret storage.
Do not use this client in browser or mobile code.
2. Request an Access Token
Use the tenant token endpoint and an allowed scope:
curl -X POST "https://your-tenant.guardhouse.cloud/connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_SERVICE_CLIENT_ID" \
-d "client_secret=YOUR_SERVICE_CLIENT_SECRET" \
-d "scope=orders.read"
orders.read is an example. Replace it with the exact scope configured for the client and API resource.
The response contains a bearer access token:
{
"access_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "orders.read"
}
Treat the token response shape as OAuth metadata; do not depend on the example lifetime.
3. Call the API
curl "https://api.example.com/orders" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
The target API validates the Guardhouse issuer, its own audience, token lifetime, and the scope required by the operation.
Use the .NET SDK
Guardhouse.SDK requests and caches service tokens:
using Guardhouse.SDK.Extensions;
using Guardhouse.SDK.Services;
builder.Services.AddGuardhouseClient(options =>
{
options.Authority = "https://your-tenant.guardhouse.cloud";
options.ClientId = "YOUR_SERVICE_CLIENT_ID";
options.ClientSecret = "YOUR_SERVICE_CLIENT_SECRET";
options.Scope = "orders.read";
options.EnableTokenCaching = true;
});
app.MapGet("/token-present", async (IGuardhouseTokenService tokens) =>
{
var accessToken = await tokens.GetAccessTokenAsync();
return Results.Ok(new { obtained = !string.IsNullOrEmpty(accessToken) });
});
Do not return the token from a real application endpoint; the route above only demonstrates acquisition without printing the credential.
Use the Node.js SDK
import { GuardhouseNodeClient } from "@guardhouse/node";
const guardhouse = new GuardhouseNodeClient({
authority: "https://your-tenant.guardhouse.cloud",
clientId: process.env.GUARDHOUSE_CLIENT_ID,
clientSecret: process.env.GUARDHOUSE_CLIENT_SECRET,
scope: "orders.read",
});
const accessToken = await guardhouse.getAccessToken();
Reuse a cached access token until the SDK renews it. Avoid requesting a new token for every API call.
Use system_api only for a backend client with System API Access explicitly enabled. It grants broad administration of the tenant and is not the scope for an ordinary application API.