These examples read data only. They use standard HTTP clients, not an official RipsCloud SDK. Store the PAT in your server's secret configuration.

## Read your workspaces




```typescript
const baseUrl = "https://api.ripscloud.com";
const token = process.env.RIPSCLOUD_TOKEN;
if (!token) throw new Error("RIPSCLOUD_TOKEN is required");

const response = await fetch(`${baseUrl}/api/v1/me/workspaces`, {
  headers: {
    Authorization: `Bearer ${token}`,
    Accept: "application/json",
  },
  signal: AbortSignal.timeout(30_000),
});
const text = await response.text();
const isJson = response.headers
  .get("content-type")
  ?.includes("application/json");
const body = isJson && text ? JSON.parse(text) : null;
if (!response.ok) {
  // Do not log the token, request body, or clinical data.
  throw new Error(
    `${response.status} ${body?.error?.code ?? "non_json_error"} ` +
      `requestId=${body?.requestId ?? response.headers.get("x-request-id") ?? "unknown"}`,
  );
}
console.log(body.items.map((workspace: { id: string }) => workspace.id));
```




```csharp
using System.Net.Http.Headers;
using System.Text.Json;

var token = Environment.GetEnvironmentVariable("RIPSCLOUD_TOKEN")
    ?? throw new InvalidOperationException("RIPSCLOUD_TOKEN is required");
using var http = new HttpClient {
    BaseAddress = new Uri("https://api.ripscloud.com"),
    Timeout = TimeSpan.FromSeconds(30)
};
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
using var response = await http.GetAsync("/api/v1/me/workspaces");
var text = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode) {
    // Do not include tokens or patient data in logs.
    var requestId = response.Headers.TryGetValues("x-request-id", out var ids)
        ? string.Join(",", ids) : "unknown";
    throw new HttpRequestException($"HTTP {(int)response.StatusCode}; requestId={requestId}");
}
using var data = JsonDocument.Parse(text);
foreach (var workspace in data.RootElement.GetProperty("items").EnumerateArray()) {
    Console.WriteLine(workspace.GetProperty("id").GetString());
}
```




## Generate types from the contract

Download [OpenAPI JSON](/openapi.json) and use a generator that supports OpenAPI 3.1. Preserve `operationId`, nullability, string identifiers, and error enums. Pin the generator version in your own project and review generated changes when you update the spec.

```typescript
// After generating paths from the downloaded OpenAPI with your chosen tool:

type Workspaces = paths["/api/v1/me/workspaces"]["get"];
["responses"][200]["content"]["application/json"];
```

Type generation checks the transport shape. It does not replace business validation or ministry acceptance.

## Add writes deliberately

For external writes, persist the idempotency key and exact body before sending. Keep retry logic outside a generic HTTP middleware: the next action depends on the package or document state. Never make a generic `POST` retry with a new key after a timeout.

Read [the recovery guide](/guides/errors-and-retries/) before adding dispatch, emission, or email to a client.
