Rydmate API
Rydmate C# (.NET) API
Connect your C# (.NET) application to Rydmate: read the fleet, hold seats and hear about every change. There is no separate library to install. The API speaks plain HTTPS and JSON, so C# (.NET)'s own tools are enough.
Before you start
- Create an API key in Rydmate under Developers. A key starting with
ryd_test_works on your test account, so nothing you try touches real trips or money. - Set it as
RYDMATE_API_KEYin your environment. Never put the key in your code or your app. - No packages to install: HttpClient and System.Text.Json come with .NET.
List your vehicles
The simplest request: every vehicle in the business, with its registration and status. If something goes wrong, the error says what, and carries a reference our team can look up.
using System.Net.Http.Headers;
using System.Text.Json;
var api = Environment.GetEnvironmentVariable("RYDMATE_API_URL") ?? "https://api.rydmate.com/api/v1";
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("RYDMATE_API_KEY"));
using var response = await http.GetAsync($"{api}/vehicles");
using var body = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
if (!response.IsSuccessStatusCode)
{
var error = body.RootElement.GetProperty("error");
throw new HttpRequestException(
$"{error.GetProperty("code")}: {error.GetProperty("message")} ({error.GetProperty("request_id")})");
}
foreach (var vehicle in body.RootElement.GetProperty("data").EnumerateArray())
{
Console.WriteLine($"{vehicle.GetProperty("registration_number")} {vehicle.GetProperty("status")}");
}Run it with dotnet run.
Hold a seat without double bookings
Hold a seat on a departure for a passenger. The Idempotency-Key header means that if the connection drops and you send the same request again, you still get one hold, not two.
If another counter took the seat first, Rydmate answers with a conflict instead of booking it twice. Once the passenger has paid, confirm the hold with POST /bookings/{id}/transition and {"to": "CONFIRMED"}.
using System.Net;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
var api = Environment.GetEnvironmentVariable("RYDMATE_API_URL") ?? "https://api.rydmate.com/api/v1";
var tripId = Environment.GetEnvironmentVariable("TRIP_ID");
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("RYDMATE_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Post, $"{api}/trips/{tripId}/bookings")
{
Content = new StringContent(JsonSerializer.Serialize(new
{
seat_number = "3A",
passenger = new { full_name = "Ngozi Okafor" },
channel = "PUBLIC_WEB",
}), Encoding.UTF8, "application/json"),
};
// Keep this key and send it again on a retry: you get one hold, never two.
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
using var response = await http.SendAsync(request);
using var body = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var root = body.RootElement;
if (response.StatusCode == HttpStatusCode.Conflict)
Console.WriteLine($"Seat already taken: {root.GetProperty("error").GetProperty("message")}");
else if (!response.IsSuccessStatusCode)
throw new HttpRequestException(
$"{root.GetProperty("error").GetProperty("code")}: {root.GetProperty("error").GetProperty("message")}");
else
Console.WriteLine($"Seat held {root.GetProperty("data").GetProperty("id")}");Check that an update really came from Rydmate
Rydmate tells your system the moment a trip, ticket, delivery or payment changes. Each update is signed with your endpoint's secret. Check the signature before you act on it, and refuse anything older than five minutes.
using System.Security.Cryptography;
using System.Text;
/// <summary>Checks the Rydmate-Signature header on a webhook delivery.</summary>
public static class RydmateSignature
{
public static bool Verify(string secret, string header, byte[] rawBody, int toleranceSeconds = 300)
{
string? t = null, v1 = null;
foreach (var part in header.Split(','))
{
var kv = part.Trim().Split('=', 2);
if (kv.Length != 2) continue;
if (kv[0] == "t") t = kv[1];
if (kv[0] == "v1") v1 = kv[1];
}
if (t is null || v1 is null || !long.TryParse(t, out var unix)) return false;
if (Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - unix) > toleranceSeconds) return false;
var signed = Encoding.UTF8.GetBytes(t + ".").Concat(rawBody).ToArray();
var expected = Convert.ToHexString(HMACSHA256.HashData(Encoding.UTF8.GetBytes(secret), signed)).ToLowerInvariant();
return CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(expected), Encoding.UTF8.GetBytes(v1));
}
}Build on Rydmate
Connect your product to real transport operations
Start on a test account, then go live when your integration is ready. Book a demo to talk through what you are building.