Skip to content
gRPC API reference

gRPC API reference

FACE is a gRPC API first. The cockpit uses the same public services described here, so any action in the cockpit can also be done by an integration. This section is the reference for that API: how to connect and authenticate, the conventions every service follows, and one page per domain listing each RPC with its messages, fields and errors.

The reference comes from the .proto definitions and the server implementation. Where the two disagree, the page describes what the server does.

At a glance

Protobuf packagesemantics.v1
API version1.0.0 (see Versioning)
TransportsNative gRPC over HTTP/2 with TLS; gRPC-web for browsers
Authenticationauthorization: Bearer <session token> metadata on every call except two
Services30 public services with 117 RPCs, plus internal RPCs (see Internal services)

Domains

Connecting

Connect to your FACE instance through the platform edge, over TLS. The edge address is the host name your instance is published at. This reference uses the placeholder face.example.internal:443. Both transports reach the same services on that address:

  • Native gRPC (HTTP/2 + TLS). Use this for server-to-server integrations, runners and command-line tools. It is the only transport for client-streaming and bidirectional RPCs.
  • gRPC-web. Use this for browser clients. The FACE cockpit is a gRPC-web client served from the same origin as the API, and it sends the same bearer token as any other client. gRPC-web carries unary and server-streaming RPCs only.

The cockpit also sends an x-agent-trace-id metadata header on every call. The value is a random id minted once per cockpit session. ActivityService uses it to scope a subscription to the runs that session started (see Lineage & activity). Other clients may send their own id or omit the header.

Do not build a client on server reflection. It is restricted to platform-internal callers. Build your client from the published .proto files instead (see Getting the protos).

Authentication

Every RPC requires a session token in the authorization metadata, except these two:

RPCWhy it is open
semantics.v1.IdentityService/LoginIt is how a session is obtained.
semantics.v1.ActivationService/ValidateLicenseIt checks a licence before anyone can sign in.

Nothing else is exempt, including the landing dashboard. Server reflection is not bearer-token authenticated, but it is restricted to the host itself and to verified mutual-TLS mesh peers. It is not an anonymous surface.

Getting a token. Call IdentityService/Login with one of these methods:

  • Email and password, followed by a TOTP code if the account has two-factor enabled.
  • An OIDC ID token from the identity provider configured for your deployment. The email in the token must be verified and must be on the deployment’s allowlist.

A successful login returns a signed session token that is valid for 12 hours. Send it on every call:

authorization: Bearer <token>

Sessions are checked against the server’s session store on every request. A token that was revoked by Logout, or by an admin changing the account, stops working within seconds on every replica.

Machine clients. An org admin can mint a service-account token with GenerateServiceAccountKey. It is valid for 365 days and scoped to the admin’s tenant. Store it as a secret.

Tenant scope. The tenant comes from the verified session, never from a request field. A request field that names a tenant is accepted only when it matches the session’s tenant.

Roles

Each session carries one role:

RoleSummary
ROLE_ORG_ADMINEverything, including user management, service-account keys and org-admin-only decisions.
ROLE_WRITERRead and write domain data and run agents. No user management.
ROLE_READERRead-only on most services. Some writes, such as setting a compute budget, are refused.
ROLE_SERVICE_ACCOUNTMachine credential. Refused on every management surface (below).

Every service page lists its handler-level role checks. These checks apply across the whole API:

  • Service accounts, on unary calls, are refused on every ConfigService RPC except ListRunners and ListConnections, on all of ActivationService, on every IdentityService RPC except ListInstances, and on member and role management. On streaming calls they are refused on all ConfigService and ActivationService streams.
  • An unrecognised role grants nothing. The session is refused with PERMISSION_DENIED.
  • Subscription tier. On the Lite tier, ConfigService/CreateDatabricksCluster is refused with PERMISSION_DENIED.
  • Licence. When the deployment has a licence configured and it is expired or invalid, every authenticated call fails with PERMISSION_DENIED (license expired or invalid).

Status codes

FACE uses standard gRPC status codes. The grpc-message text is written for people, and the cockpit shows it verbatim for refusals. Clients may show it too, but should branch on the code.

CodeWhen FACE returns it
UNAUTHENTICATEDNo authorization metadata, or a token that is malformed, expired, revoked or not issued by this deployment. Sign in again.
PERMISSION_DENIEDThe session is valid but not allowed: wrong role, service-account restriction, subscription tier, another tenant’s resource, or an expired licence.
INVALID_ARGUMENTA required field is missing or a value is malformed.
FAILED_PRECONDITIONThe request is well formed but the instance cannot serve it yet. Typical causes: no data source is connected, the sovereign model plane is not configured, or a required integration is not set up. Fix the configuration and retry.
NOT_FOUNDThe named record, trace, connection or schedule does not exist for this tenant.
DEADLINE_EXCEEDEDA runner accepted dispatched work but did not answer in time. The run may still be in progress on the runner, so this does not mean it failed.
RESOURCE_EXHAUSTEDThe caller exceeded the per-caller rate limit, where the operator has enabled one, or a budget or size limit. Back off and retry.
UNIMPLEMENTEDThe RPC is in the protos but not served. Each such RPC is marked on its page.
UNAVAILABLEA dependency, such as a runner or the model plane, is temporarily unreachable. Safe to retry with backoff.
INTERNALThe server failed. Nothing is claimed to have happened.

Many RPCs also report an expected refusal in the response body (success: false plus message) instead of an error. Each RPC’s section says which style it uses.

Unmeasured is not zero. Several responses use explicit presence (proto3 optional) or a stated reason to separate “nothing measured this” from a measured zero, for example confidence fields and usage figures. When a field is absent, report it as not measured. Do not display it as 0.

Streaming

KindRPCsTransports
Server streamingFetchService/RunFetchStream, TwinsService/StreamTwins, TwinsService/UploadAnalyze, HypothesisService/SimulateScenario, SurveillanceService/SubscribeTelemetry, ActivityService/SubscribeAgentActivity, RalphOrchestratorService/ExecuteLoopNative gRPC and gRPC-web
Bidirectional streamingHypothesisService/InteractiveSimulate, FetchService/Talk, RunnerEnrollmentService/EnrollNative gRPC only

Streams are authenticated once, when they open, with the same bearer token and the same rules as unary calls. A long-lived stream therefore keeps running after its token expires. Re-open it with a fresh token when you reconnect. Set a deadline (grpc-timeout) on unary calls and reconnect server streams with backoff.

Versioning

The protos form one module with one version, currently 1.0.0. The build lints the module with buf and runs a breaking-change check against the previous release. A change that breaks the wire format or generated code is rejected unless it is explicitly listed as an exception, with the reason recorded. Additive changes (new fields, RPCs and enum values) arrive without notice. Clients should ignore unknown fields and treat unknown enum values as unspecified.

Where a field has been retired, its number and name are reserved, so they are never reused with another meaning. Deprecated RPCs keep working for at least one release and are marked on their pages.

Getting the protos

The .proto files are provided with the platform. The module is semantics/v1/*.proto under a buf module root. It imports:

  • google/protobuf/timestamp.proto (well-known types), and
  • runink/ui/judgement/v1/judgement.proto, the platform’s shared judgement types, which ship with the FACE protos.

Generate clients with buf generate or protoc for your language. All messages use proto3.

Worked example

This example signs in with grpcurl, then makes an authenticated call. grpcurl reads the protos from disk rather than using reflection. Run it from the directory that holds the proto module root (semantics/) and the shared runink/ import tree.

grpcurl \
-import-path . \
-proto semantics/v1/commons_defs.proto \
-d '{"method": "AUTH_METHOD_CREDENTIALS",
     "username": "analyst@example.com",
     "password": "'"$FACE_PASSWORD"'"}' \
face.example.internal:443 \
semantics.v1.IdentityService/Login

A successful response:

{
"status": "STATUS_SUCCESS",
"token": "eyJhbGciOi...",
"message": "Authentication Successful"
}

If the account has two-factor enabled, the response is STATUS_MFA_REQUIRED with an mfaSession. Send it back within 5 minutes:

grpcurl -import-path . -proto semantics/v1/commons_defs.proto \
-d '{"method": "AUTH_METHOD_MFA_VERIFY",
     "mfaSession": "'"$MFA_SESSION"'", "mfaCode": "123456"}' \
face.example.internal:443 semantics.v1.IdentityService/Login

grpcurl prints and accepts JSON field names in lowerCamelCase (mfaSession), and it also accepts the proto names (mfa_session). Keep passwords and tokens out of your shell history. The example reads them from environment variables.

Shared types

Judgement

runink.ui.judgement.v1.Judgement is the platform’s verdict on one claim, usually an action an agent proposed. It appears in fetch results, action cards and the orchestrator stream.

FieldTypeDescription
verdictVerdictThe verdict.
reason_codestringStable reason code, for example evidence-contradicts-the-claim.
sentencestringThe sentence a person can act on. It may be partly model-written: render it as text, never as markup.
basisBasisWhether a model was involved.
subjectstringWhat was judged, as a person reads it: the action or card title.
claimstringThe claim judged about the subject.
acceptedboolfalse means the verdict was a dissent and the action was removed from the answer.
judged_atgoogle.protobuf.TimestampWhen the judgement ran. Unset means not recorded. It never means “now”.
refstringWhere the action sat in the answer, for example decisions[0].
evidence_itemsint32How many evidence items were weighed. 0 with an evidence reason code is a real zero. Otherwise 0 may mean “not reported”.
roundint320 for the first answer. 1 and higher for answers the agent loop revised.
verdict_textstringThe verdict spelled out verbatim. Show it when verdict is VERDICT_UNSPECIFIED.

JudgementSet

Every verdict from one run, accepted and rejected, with the server’s counts.

FieldTypeDescription
judgementsrepeated JudgementThe verdicts. This may be one page of a longer list.
concursint32Concurring verdicts.
dissentsint32Dissenting verdicts.
unableint32Unable-to-judge verdicts.

Use the counts as sent. Do not recompute them from judgements.

Verdict

ValueMeaning
VERDICT_UNSPECIFIEDNot judged, or a verdict this enum does not know. Show verdict_text.
VERDICT_CONCURThe evidence supports the claim.
VERDICT_DISSENTThe evidence contradicts the claim. reason_code names what.
VERDICT_UNABLE_TO_JUDGEThe evidence is absent, unreadable or does not bear on the claim. Never agreement.
VERDICT_OUT_OF_SCOPEThe platform has no standing over the subject. Counted in no total. FACE does not produce it.

Basis

ValueMeaning
BASIS_UNSPECIFIEDNot stated.
BASIS_DETERMINISTICGates and arithmetic only. No model was consulted.
BASIS_MODELA sovereign model answered the qualitative question.

Internal services

semantics.v1.ModelService (Generate, Embedding, SynthesizeSpeech, SpeakFetchSummary) is FACE’s internal interface to its own sovereign model plane. It accepts calls only from the host itself and refuses every other caller with UNAUTHENTICATED, whatever token is presented. It is not part of the integration surface and is not documented here. Model-backed features are reached through the domain services that use them.

FetchService/GetDispatchKey is also internal: only a runner serves it, and only to a verified mesh peer.

The same endpoint also serves the platform’s shared cockpit components: estate map, data sources, billing, profile and member administration. Those services are defined outside the semantics.v1 package and are not covered by this reference.