API Concepts#

Versioning#

The Fleet API adopts a continuous release model to provide our users with rapid access to product innovation, enhancements and security patches, while maintaining the highest level of quality. The API consists of multiple services, each of which is versioned independently.

Release Cadence#

Announcements regarding releases will be made in the changelog as well as through the communication channels agreed upon in the contract. Additionally, we will provide a roadmap outlining the planned features for the upcoming releases, covering at least the next quarter. This roadmap is intended to assist with planning and provide visibility into future developments.

Proto Package Versioning#

We version our API through proto package versioning and include the version number in the package name. Backwards compatibility is maintained within the same version of a package. When a breaking change is introduced, a new version of the package is created.

All changes will be reported in the changelog regardless if they are breaking or not.

Non-Breaking Changes#

These changes are non-breaking at gRPC protocol level and binary level.

  • Adding a new service

  • Adding a new RPC to an existing service

  • Adding a new field to a request or response message

  • Adding a new enum value

  • Renaming a field

Binary Breaking Changes#

The following changes are non-breaking at a gRPC protocol level, but depending on the programming language used, they may be breaking at a binary level.

  • Removing a field

  • Renaming a Message

Protocol Breaking Changes#

The following changes are breaking at a gRPC protocol and binary level.

  • Removing a service or RPC

  • Changing a field type

  • Changing a field number

  • Renaming a package, service or RPC

Example of a breaking change which would result in a new version of the package:

Rename of a proto message

// Version 1
syntax = "proto3";
package moia.fleet.state.v1;

message VehicleConfiguration {
  string id = 1;
  string label = 2;
}

// Version 2
syntax = "proto3";
package moia.fleet.state.v2;

message VehicleProperties {
  string id = 1;
  string label = 2;
}

Clients can import the specific version they want to use, and changes to the API can be introduced in a new version while maintaining support for the older version.

Support Policy#

We provide support for the current version of the service and continuously update it with non-breaking changes. When breaking changes require the release of a new version, the previous version will be deprecated but continued to be supported for the period agreed upon in the contract. This allows users to upgrade to the newer version when it aligns with their business requirements. However, we strongly recommend using the latest version of the API to take advantage of the latest features and improvements.

Support means that a previous version will remain available and operational, and bug and security fixes will be provided.

Beta Versions#

Beta versions are not as stable and while we try to avoid breaking changes within the same beta version, they may occur. We also do not guarantee that beta versions will be supported for the same duration as stable versions.

Pagination#

We use Pagination for all our List endpoints. You can optionally pass a page_size parameter to limit the amounts of items returned.

For Example:

grpcurl -H "authorization: Bearer ${ACCESS_TOKEN}" -import-path . -proto fleet_state.proto \
-d "{ \"fleet_id\": \"$FLEET_ID\", \"page_size\": 2 }" \
fleet-api.trip.int.moia-group.io:443 moia.fleet.state.v1beta4.FleetStateService/ListVehicles

Example output:

{
  "vehicles": [
    {
      "id": "94d36e21-ca69-4a5b-b2b7-8068122e7362",
      "label": "429"
    },
    {
      "id": "76350d1a-8df5-4217-8d58-207f4e1e0b90",
      "label": "1005"
    }
  ],
  "nextPageToken": "c688a598-9a67-4dde-b2b3-98992a051bb0"
}

To query the next page use the returned page token with NEXT_PAGE_TOKEN="c688a598-9a67-4dde-b2b3-98992a051bb0":

grpcurl -H "authorization: Bearer $ACCESS_TOKEN" -import-path . -proto fleet_state.proto \
-d "{ \"fleet_id\": \"$FLEET_ID\", \"page_token\": \"$NEXT_PAGE_TOKEN\", \"page_size\": 2 }" \
fleet-api.trip.int.moia-group.io:443 moia.fleet.state.v1beta4.FleetStateService/ListVehicles

Example output:

{
  "vehicles": [
    {
      "id": "3245cadd-a80c-4524-a5d8-6507479b7921",
      "label": "430"
    }
  ]
}

Server-Side Event Streaming#

We use server-streaming RPCs to push events to clients. Events are pushed to the client as long as the streaming connection is alive. The streaming connection can break at any point due to timeouts, network failures or server errors. In the case of a connection being interrupted, the client needs to reconnect by calling the streaming RPC again.

Depending on the kind of event we offer two streaming types: durable streams and non-durable streams.

Durable Streams#

Durable streams enable a reliable message delivery where past events can be retrieved within the retention window even if the streaming connection is not active when the event occurs. It is used in scenarios where events should not be missed.

Each message sent over a stream contains a message_id.

message StreamResponse {
  Event event = 1;
  string message_id = 2;
 }

By providing the last received last_message_id in the streaming request in cases of an interruption of the stream or connection, all events after the last received one are replayed.

message StreamRequest {
  string event_id = 1;
  optional string last_message_id = 2;
}

On initial connection, an event is emitted which contains only a message_id and no event e.g. {"event":null,"message_id":"1231231321-0"}. This message_id can be used as a starting point in case no event is transmitted during the lifetime of the stream.

(Optional) Polling#

In addition to durable streaming endpoints, we offer unary polling endpoints for clients that do not support gRPC streaming. Polling endpoints are used to retrieve events that occurred since the last poll. The polling response can contain 0 or more events, but will always return a message_id which can be used in the next request.

 message PollResponse {
   repeated Event events = 1;
   string message_id = 2;
 }

The same message_id concept as in durable streams is used to retrieve events that occurred since the last poll. If last_message_id is not provided in the request, the server will always return just a message_id and no events.

 message PollRequest {
   string event_id = 1;
   optional string last_message_id = 2;
 }

Non-Durable Streams#

Non-durable streams only last for the lifetime of the streaming connection. This type of streaming is used when the latest message contains the full state, and earlier events are outdated once a newer event has been sent. Note that you can only ensure to have the latest message if you have an active streaming connection.

Errors#

Fleet API uses gRPC richer error handling. The gRPC response codes indicate the success or failure of an API request. In addition, Fleet API provides detailed error messages when applicable to assist engineers in diagnosing issues. Commonly used error details are documented here. Additionally, potential errors and details for each endpoint are documented in the protobuf definitions.

Code

Status

Description

Error Details

0

OK

OK is returned on success.

1

Canceled

Canceled indicates the operation was canceled (typically by the caller).

2

Unknown

Unknown error.

3

InvalidArgument

InvalidArgument indicates client specified an invalid argument.

BadRequest detail for every invalid field

4

DeadlineExceeded

DeadlineExceeded means operation expired before completion.

5

NotFound

NotFound means some requested entity (e.g., file or directory) was not found.

ResourceInfo to provide details about resource which was not found, ErrorInfo if pagination token was not found.

6

AlreadyExists

AlreadyExists means an attempt to create an entity failed because one already exists.

7

PermissionDenied

PermissionDenied indicates the caller does not have permission to execute the specified operation.

8

ResourceExhausted

ResourceExhausted indicates some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space.

9

FailedPrecondition

FailedPrecondition indicates operation was rejected because the system is not in a state required for the operation’s execution. For example, directory to be deleted may be non-empty, an rmdir operation is applied to a non-directory, etc.

10

Aborted

Aborted indicates the operation was aborted, typically due to a concurrency issue like sequencer check failures, transaction aborts, etc.

11

OutOfRange

OutOfRange means operation was attempted past the valid range.

12

Unimplemented

Unimplemented indicates operation is not implemented or not supported/enabled in this service.

13

Internal

Internal errors. Means some invariants expected by underlying system has been broken. If you see one of these errors, something is very broken.

14

Unavailable

Unavailable indicates the service is currently unavailable. This is a most likely a transient condition and may be corrected by retrying with a backoff. Note that it is not always safe to retry non-idempotent operations.

15

DataLoss

DataLoss indicates unrecoverable data loss or corruption.

16

Unauthenticated

Unauthenticated indicates the request does not have valid authentication credentials for the operation.