Skip to main content

gRPC API

Some of Releval's APIs are implemented as gRPC APIs. gRPC is a modern Remote Procedure Call (RPC) framework developed by Google that provides high performance and low latency.

gRPC APIs are the recommended choice to use if the Releval API, your integration language of choice, and your environment support it.

Protocol Buffers

The gRPC APIs are defined using Protocol Buffers, a powerful language-neutral, platform-neutral serialization toolset and language that makes it easy to automatically generate idiomatic clients in a variety of languages and platforms.

The protocol buffer definition (proto) files are available to download:

Proto FileDescription
user_behavior_insights.protoUser Behavior Insights Messages
user_behavior_insights_service.protoUser Behavior Insights Service

Well-Known Types

Google Protocol Buffers Well-Known Types are a set of predefined, commonly used message types that are included in the protobuf library to simplify development and ensure interoperability. These types cover a wide range of standard data representations, are available out-of-the-box and are designed to represent common concepts, such as timestamps, durations, wrappers for primitive types, and more.

Releval's gRPC APIs use Well-Known Types where suitable.

Discoverability

Releval exposes a gRPC reflection service which can be queried to discover the gRPC services on the server. Tools such as grpcurl can be used to query the service:

grpcurl ${RELEVAL_HOST}:${PORT} describe

which may return a response similar to:

user_behavior_insights.v1.UserBehaviorInsightsService is a service:
service UserBehaviorInsightsService {
rpc TrackEvent ( .user_behavior_insights.v1.TrackEventRequest ) returns ( .user_behavior_insights.v1.TrackEventResponse );
rpc TrackQuery ( .user_behavior_insights.v1.TrackQueryRequest ) returns ( .user_behavior_insights.v1.TrackQueryResponse );
}
grpc.reflection.v1alpha.ServerReflection is a service:
service ServerReflection {
rpc ServerReflectionInfo ( stream .grpc.reflection.v1alpha.ServerReflectionRequest ) returns ( stream .grpc.reflection.v1alpha.ServerReflectionResponse );
}

Authentication

Releval uses Bearer tokens to authorize requests, which are obtained using the OAuth 2.0 Client Credentials Flow, using the client_id and client_secret generated upon creating an app client. Consult the OAuth documentation for steps on how to create an app client.

gRPC provides a generic mechanism to attach metadata based credentials to requests and responses using Call Credentials. Many gRPC language implementations allow a Bearer token to be acquired as part of the request flow.

Here's an implementation of CallCredentials for C# clients that can be used to get access tokens on demand when making requests.

// Copyright 2025 Releval
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Grpc.Core;

namespace Releval;

/// <summary>
/// OAuth 2.0 authentication using JWT tokens.
/// </summary>
public class OAuth2CallCredentials : CallCredentials, IDisposable
{
private readonly OAuth2TokenService _tokenService;

/// <summary>
/// Instantiates a new instance of <see cref="OAuth2CallCredentials"/>
/// </summary>
public OAuth2CallCredentials(OAuth2TokenService tokenService) =>
_tokenService = tokenService;

/// <inheritdoc />
public override void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object? state) =>
configurator.SetAsyncAuthInterceptorCredentials(state, AsyncAuthInterceptor);

private async Task AsyncAuthInterceptor(AuthInterceptorContext context, Metadata metadata)
{
var accessToken = await _tokenService.GetAccessTokenAsync(context.CancellationToken).ConfigureAwait(false);
metadata.Add("Authorization", $"Bearer {accessToken}");
}

public void Dispose() => _tokenService.Dispose();
}

To use this to construct a gRPC channel to use with generated C# clients

// Copyright 2025 Releval
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


var address = "https://app.releval.co";
var tokenService = new OAuth2TokenService(clientId, clientSecret, $"{address}/oauth2/token");
var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(
ChannelCredentials.SecureSsl,
new OAuth2CallCredentials(tokenService))
});

// use the channel with the generated client.

Authorization

When creating an app client, a collection of roles are specified that determine what the app client has access to. These roles are encoded within the JSON Web Token (JWT) bearer token, and can be viewed using jwt.io.

Info

In all cases, if an app client does not have permission to do something, you'll get a PERMISSION_DENIED error.

Errors

The Releval API uses the following gRPC status codes:

CodeNumberDescription
OK0Not an error; returned on success.
CANCELLED1Your request was cancelled, typically by you.
UNKNOWN2We've got some problem with our service. Please try again later.
INVALID_ARGUMENT3Your request is malformed in some way. The response usually indicates what's wrong.
DEADLINE_EXCEEDED4A deadline expired before the request could complete. For requests that change the state of the system, this error may be returned even if the request has completed successfully.
NOT_FOUND5The specified resource was not found.
ALREADY_EXISTS6The resource that you're trying to create already exists.
PERMISSION_DENIED7Your request is not authorized to perform the operation.
RESOURCE_EXHAUSTED8You're making too many requests at once. Slow down!
FAILED_PRECONDITION9Your request is malformed in some way. The response usually indicates what's wrong.
ABORTED10Your request conflicted with another operation.
OUT_OF_RANGE11Your request has tried to perform some action outside of a valid range.
UNIMPLEMENTED12You've hit an operation that is not implemented or is not supported/enabled.
INTERNAL13We've got some problem with our service. Please try again later.
UNAVAILABLE14We're temporarily offline for maintenance. Please try again later.
DATA_LOSS15There's been an unrecoverable data loss or corruption.
UNAUTHENTICATED16Your request does not have valid authentication credentials for the operation.
Info

When API errors occur, it is up to you to retry your request - Releval does not keep track of failed requests.

Versioning

The Releval API is versioned. A new API version is released when we introduce a backwards-incompatible change to the API. For example, changing a field type or name, or deprecating endpoints.

While we're adding functionality to our API, we won't release a new API version. You'll be able to take advantage of this non-breaking backwards-compatible changes directly on the API version you're currently using.

Releval considers the following changes to be backwards-compatible:

  • Adding new API resources.

  • Adding new optional request parameters to existing API methods.

  • Adding new properties to existing API responses.

  • Changing the order of properties in existing API responses.

  • Changing the length or format of opaque strings such as object IDs, error messages, and other human-readable strings.

Info

Your integration should gracefully handle backwards-compatible changes. Changes at the proto level should be automatically taken care of by the Protocol Buffers tooling.