Skip to main content

B2B Auth — obtaining and using API credentials

Calls into the Ark Platform business APIs (accounts, parties, cards, payments, …) are authorised as applications, not users. The platform deliberately rejects user-interactive ("sign in with Microsoft") tokens on these routes — a plain az login will not work. You authenticate by minting a token via the OAuth 2.0 client-credentials flow in Microsoft Entra ID, then sending it as a bearer token with a few tenant-routing headers.

This page is the end-to-end path: how to obtain a credential, mint a token, make a call, and read the most common rejections.

At a glance

Before your first call — obtaining a credential

A credential is the pair client_id + client_secret of an Entra app that the Ark instance has explicitly authorised. There are six steps, split across three roles. Steps 1–2 happen in your Azure tenant; steps 3–5 happen against the Ark Platform admin API; step 6 is repeatable per developer.

#WhoWhereWhat
1Your Azure adminEntra ID (your tenant)Create an app registration. Note its Application (client) ID and generate a client secret.
2Your Azure adminEntra ID (your tenant)Assign the CLIENT app role of the Ark Platform API app registration (AUTH_MICROSOFT_ENTRA_API_ID) to the app from step 1.
3An Ark admin (ADMIN role)Ark Platform admin APIPUT /v1/admin/external-applications/{oAuthAppId} with {"slug":"<app-slug>"} — registers the Entra app with Ark.
4An Ark admin (ADMIN role)Ark Platform admin APIPUT /v1/admin/clients/{slug} with {"clientStatus":"ACTIVE","brandStatus":"ACTIVE"} — creates the client/brand tenant (slug e.g. client1-brand2) that step 5 authorises the app against. The client/brand must exist before it can be mapped.
5An Ark admin (ADMIN role)Ark Platform admin APIPUT /v1/admin/external-applications/{oAuthAppId}/clients/{clientBrandSlug} — authorises the app for a specific client/brand. {clientBrandSlug} must match the {slug} created in step 4.
6The developer making callsTheir terminal / appUse the client_id + client_secret from step 1 to mint a token (see Minting a token).

oAuthAppId in steps 3 and 5 is the Application (client) ID (a UUID) from step 1. Ark never stores the client secret — only the mapping oAuthAppId → client/brand. The secret lives in Entra; you, the customer, control it.

Where the customer/Ark/developer boundary lands

Ark is self-hosted in your Azure environment (see the hosting minimum requirements). Steps 1–2 are run by your Azure admin in your tenant. Steps 3–5 are run by whoever holds the ADMIN role on your Ark instance.

References for steps 1–2:

API reference: Administration Clients (step 4) and Administration External Applications (steps 3 and 5).

Minting a token

curl -s -X POST https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token \
-d "grant_type=client_credentials" \
-d "client_id=$CLIENT_ID" \
-d "client_secret=$CLIENT_SECRET" \
-d "scope=api://$ARK_API_ID/.default" \
| jq -r .access_token
VariableWhere it comes from
TENANT_IDYour Entra tenant id.
CLIENT_IDThe Application (client) ID from step 1.
CLIENT_SECRETThe client secret from step 1. Keep in a secret store (Key Vault, 1Password, …).
ARK_API_IDThe Application (client) ID of the Ark Platform API app registration (AUTH_MICROSOFT_ENTRA_API_ID).

The response is a JWT (access_token). Tokens are short-lived (typically one hour) — re-mint as needed.

az login won't work

az account get-access-token --resource api://$ARK_API_ID only yields an accepted token when you ran az login --service-principal … with the credential from step 1. A plain user az login produces a delegated user token with no appid claim → 403 (see Troubleshooting).

Calling an endpoint

Send the token as a bearer header. Most business endpoints additionally require the tenant-routing headers clientid and brandid; party-scoped endpoints also require partyid.

GET /v1/parties/{partyId}
Host: <your-ark-host>
Authorization: Bearer <access_token>
clientid: <client-uuid>
brandid: <brand-uuid>
partyid: <party-uuid>
HeaderWhenNotes
AuthorizationAlwaysBearer <jwt> from Minting a token.
clientidBusiness endpointsThe UUID of the client whose data you're acting on. Must match a mapping from step 5.
brandidBusiness endpointsThe UUID of the brand under that client.
partyidParty-scoped endpoints (parties, cards, accounts)The UUID of the party.
customeridCustomer-scoped endpointsWhere applicable.

The exact required headers per endpoint are declared in the OpenAPI specs (see API Reference).

Troubleshooting

SymptomLikely causeFix
401 UnauthorizedToken missing, malformed, expired, signed by a tenant Ark doesn't trust, or audience mismatch.Re-mint the token. Check $TENANT_ID matches the tenant Ark is configured for and scope is api://$ARK_API_ID/.default.
403 AUT001002 External application does not have access to the requested resourceOne of: (a) the token has no appid claim — it is a user token, not a client-credentials token; (b) the app from step 1 has not been registered + mapped, or its client/brand was never created (steps 3–5); (c) the app is registered but not mapped to the clientid/brandid you sent.Confirm the token was minted via client-credentials. Confirm an admin completed steps 3 through 5 against the exact client/brand slug you're using.
401 GEN001006RolesGuard rejection — the token is valid but the app doesn't carry the CLIENT role.Re-do step 2. The role must be the CLIENT app role on the Ark Platform API app registration.

Try it from the docs

Every endpoint page in the API Reference has a Try it panel. Mint a token as above, paste it into the bearer field, fill the clientid/brandid (+ partyid where applicable) headers, and send.