render_api 0.1.0 copy "render_api: ^0.1.0" to clipboard
render_api: ^0.1.0 copied to clipboard

Unofficial Dart client for the Render REST API, covering workflows, tasks and task runs. Not affiliated with or endorsed by Render.

render_api #

⚠️ UNOFFICIAL #

An independent, community-built project. Not affiliated with, endorsed by, or supported by Render.

Render's own SDKs and documentation are at render.com/docs.

Render  Built for Render.

The Render name and logo are trademarks of Render Services, Inc. The mark is reproduced unaltered from Render's brand kit, referentially, to identify the service these packages work with — not to suggest any endorsement.

A typed Dart client for the Render REST API, covering the workflows surface: workflow services, versions, task definitions and task runs.

Works on Dart and Flutter, including Web. Depends only on package:http.

Usage #

final render = RenderApi();               // reads RENDER_API_KEY

final run = await render.taskRuns.run(
  'my-workflow/sumSquares',
  [[2, 3, 4]],
);
print(run.result);                        // 29

render.close();

On the web there is no environment, so pass the token explicitly: RenderApi(token: ...).

Typed responses #

Every operation that returns JSON returns a typed model. Two things in the spec would otherwise have left large gaps:

Roughly a third of responses describe their shape inline rather than by reference. Each of those gets a class named after its operation, so getWorkflow returns a GetWorkflowResponse, not a Map.

A handful describe a value as oneOf several shapes with no discriminator. Where the variants can be told apart by which fields are present, they become a sealed class — so a switch over them is exhaustive, and adding a variant is a compile error rather than a silent fallthrough:

final details = EnvSpecificDetails.fromJson(json);
final summary = switch (details) {
  EnvSpecificDetailsDocker() => 'built from a Dockerfile',
  EnvSpecificDetailsBuild()  => 'built with a native runtime',
};

Two unions stay raw JSON, honestly: events.details has sixty-eight variants with no distinguishing field, and service.serviceDetails is discriminated by a sibling type the schema cannot see from inside the property.

Another handful compose their response with allOf — the env-group endpoints all do. Since the spec uses it only to combine plain objects, those are merged into one class: EnvGroup carries the fields of both members.

Enums with identical value sets are one type rather than many: every response carrying a region shares Region, instead of each getting its own structurally-identical copy.

Why the errors are opinionated #

Render's API frequently reports failures without saying what went wrong. Creating a workflow against a repository its Git app cannot read returns a bare 500 internal server error; that one cost an hour of debugging and four accidental workflow services. So failures here are typed, and carry a hint naming the likely cause where one can be inferred:

try {
  await render.createWorkflow(body: {...});
} on RenderServerException catch (e) {
  print(e.hint);
  // Render returns a bare 500 here when it cannot reach the repository.
  // Check that the Render GitHub/GitLab app has been granted access to it...
}

It answers 500 rather than 404 for an unknown task run id, too. Both hints exist because the bare status cost real debugging time.

The same instinct applies to limits Render enforces remotely: a task input over 4 MB is rejected locally, before the request, so the error names the real problem.

Retry policy #

429 is always retried, honouring Retry-After — nothing was processed. 5xx is retried only for GET, HEAD and DELETE: a POST that fails with 5xx may still have taken effect, and retrying it could create duplicates.

Pagination #

List endpoints return a Stream, and walk cursors for you:

await for (final w in render.workflows.list()) { ... }

final recent = await render.taskRuns.list(max: 50).toList();

Use the *Page variants if you want to hold cursors yourself.

Watching runs #

waitFor and run poll, and work on every platform including Flutter Web.

events streams server-sent events instead, but will not work on Flutter Web with the default HTTP clientpackage:http's BrowserClient buffers whole responses. Inject a streaming client (package:fetch_client) there, or poll.

Testing #

dart test                          # offline, no credentials needed
dart run example/smoke.dart        # live, needs RENDER_API_KEY

Coverage #

All 208 operations across 26 resource groups, generated from the vendored OpenAPI spec, with 164 typed models.

Two routes to the same API #

Every operation is named exactly as Render names it, because both this package and Render's official Node bindings derive their names from the spec's operationId. An example from the docs translates directly:

// @api/render-api
renderApi.listHeaders({limit: '20', serviceId: 'serviceId'})
// flat — the same spelling
await render.listHeaders(serviceId: 'srv-x', limit: 20);

// grouped — the same call, organised by resource
await render.raw.services.listHeaders(serviceId: 'srv-x', limit: 20);

Query parameters are typed from the spec rather than passed as strings, so limit is an int and repeated filters are a List<String>.

Running workflow tasks #

Starting and watching task runs lives in package:render_workflows, which depends on this package for its transport. Render splits the same way: @renderinc/sdk runs tasks, @api/render-api covers REST.

Workflow services — creating them, deploying versions, listing task definitions — are REST, and generated here.

Per-method reference #

doc/api/ documents every operation: signature, parameters with Render's own descriptions, the fields of what it returns, and a link to the matching page on api-docs.render.com. Generated alongside the code, so the two cannot drift.

Verified against the documentation #

Every reference page on api-docs.render.com embeds a scoped OpenAPI fragment for its endpoint — the same spec vendored here. All 225 documented operations were diffed against it: parameters, request bodies and response shapes agree throughout. The docs and this client are two renderings of one source.

Regenerating #

dart run tool/generate.dart

The spec is vendored at tool/render-openapi.json with a checksum beside it. Render notes that the spec is unversioned and names may change, so regenerate deliberately: test/parity_test.dart fails if the generated surface stops matching the spec's operation set.

2
likes
0
points
475
downloads

Publisher

verified publisherhiveright.tech

Weekly Downloads

Unofficial Dart client for the Render REST API, covering workflows, tasks and task runs. Not affiliated with or endorsed by Render.

Repository (GitHub)
View/report issues

Topics

#render #rest #api-client #workflows

License

unknown (license)

Dependencies

http, meta

More

Packages that depend on render_api