Client libraries
The OpenAPI document is generated from the same code that serves the API, and the rhino-relay command line is generated from it. Point any OpenAPI 3.1 generator at it to get a library in your language. Everything a library needs beyond plain OpenAPI is in a few x- fields, described here, so a generated library and the CLI name and behave the same.
Each operation has one tag, its resource group, and an operationId of the form verb then resource (getCampaignReport). x-client gives the short names:
"x-client": { "group": "campaigns", "method": "report" }Use group for the library’s namespace and method for the method: client.campaigns.report(id). The CLI uses the same names in kebab-case: rhino-relay campaigns report <id>. Each tag’s x-group and description give the namespace and its documentation.
Retries
Section titled “Retries”x-idempotency says how a request may be retried after a timeout or a 5xx:
| Value | Meaning |
|---|---|
key-required |
Send an Idempotency-Key (make one up per call); retry with the same key |
key-optional |
Same, when you send a key; without one, don’t retry automatically |
safe |
Repeating the request changes nothing further (reads, updates, deletes, state changes) |
unsafe |
Never retry automatically. Only POST /keys: the new secret is returned once and never stored for replay |
429 and 503 responses carry Retry-After. A replayed response carries Idempotent-Replayed: true. See Idempotency.
Pagination
Section titled “Pagination”Lists carry x-pagination, so a generator can make them iterable:
"x-pagination": { "type": "cursor", "limitParam": "limit", "cursorParam": "cursor", "itemsField": "data", "nextCursorField": "nextCursor" }Follow nextCursor until it’s null. See Pagination.
Waiters
Section titled “Waiters”Imports, exports, campaigns and setup take a while. The GET operations that show their progress carry x-waiters, in the shape of AWS SDK waiters: poll every delaySeconds, up to maxAttempts times, until a response field matches an acceptor.
"x-waiters": { "ready": { "description": "The export is written and downloadUrl is set", "delaySeconds": 5, "maxAttempts": 720, "acceptors": [ { "path": "state", "expected": "ready", "state": "success" }, { "path": "state", "expected": "failed", "state": "failure" } ] }}The requests that start the work (POST /exports, the import calls, /schedule, /resume and /setup/verify) carry a standard OpenAPI response link to the GET, with the new resource’s id, so a library can offer “create and wait”. In the CLI that’s --wait: rhino-relay exports create --data '{"kind":"contacts"}' --wait ready.
| Operation | Waiter | Succeeds when | Stops early when | Polls every |
|---|---|---|---|---|
campaigns.get | completed: Every stage has gone out. A pause or cancel ends the wait, since it needs you to act | state = completed | state = paused, state = cancelled | 30 seconds |
imports.get | dryRunReady: The dry run is ready to review and commit (or the import went further) | state = dry_run_ready, state = committing, state = completed | state = failed, state = cancelled | 5 seconds |
imports.get | completed: The import is committed | state = completed | state = failed, state = cancelled | 10 seconds |
exports.get | ready: The export is written and downloadUrl is set | state = ready | state = failed | 5 seconds |
health.get | healthy: Every setup and sending check passes (DNS can take a while to spread) | ok = true | — | 30 seconds |
Every object and enum in a request or response is a named schema, so libraries get the same readable type names. Unions have a type field and a discriminator, so each kind gets its own type: segment conditions (tag, field, score, clicked, opened, created and nested group) and stage plans (preset and custom). Contacts, segments, campaigns and settings send their version as an ETag, which If-Match takes back.
Hosts and credentials
Section titled “Hosts and credentials”servers lists every host: the home Region (marked x-region), other Regions (a {region} variable) and your custom domain. The only security scheme is the API key, a standard bearer token, so every generated library works with it as it is.
SigV4 isn’t a security scheme, because OpenAPI has none for it and generators would try to send it as a fixed header. x-sigv4 at the top of the document describes it instead: your Region’s SigV4 endpoint and the signing service. To use it from a library, point the library at that endpoint and sign each request with the AWS SDK’s signer in its request hook, as in Authentication.
Errors are application/problem+json with a code from a fixed list (x-error-codes at the top of the document), so a library can raise one error type per code. See Errors.