Read an account's contacts
POST/accounts/:accountId/contacts/get
Returns the primary contact, the three alternate contacts and the root email address AWS holds for one account.
This is a read, despite being a POST. Two reasons, neither of them an oversight. It mirrors the ops-service route it forwards to, which is shaped as an RPC call rather than as a REST resource, so Prism relays the method unchanged. And Prism's own console treats it as a read: it is one of a small set of paths explicitly carved out of the read-only guard, so an operator with read-only access can still open the contacts page. The request body is not the reason; this operation sends none and reads none.
The response is not wrapped in the success envelope. It is the
ops-service's answer relayed byte for byte, so the contacts are at the top
level with no success, no message and no data. It is the only
operation documented here that answers this way. A client that reaches
for response.data will find nothing.
How the contacts operations reach AWS
This operation and the other five under /contacts are proxies. Prism
does not call AWS for them: it forwards the request to CloudKeeper's
ops-service, which holds the payer-account access that reading and writing
account contacts requires.
They are present on every deployment, CloudKeeper-hosted and
self-hosted alike; none of them 404. What differs is whether the proxy
has anywhere to go. A self-hosted install that has not been paired with
CloudKeeper SaaS answers every one of them with 502 and the message
no SaaS connection configured — pair with CloudKeeper SaaS first; pair
the install and they start working.
Every failure past that point is also a 502, and this is the single
most important thing to know about these six operations. Prism collapses
the whole upstream outcome into one status: a transport failure, a
timeout, an ops-service 400 for a malformed body, an ops-service 403, and
an ops-service 404 for an account that does not exist all arrive as 502
with the upstream message in message and error. You cannot tell "no
such account" from "the ops-service is down" by status code. Read
message; it is the only signal.
On CloudKeeper-hosted Prism the tenant segment of the path is forwarded to the ops-service as the realm name, so for these six address your tenant by its slug rather than by its UUID.
Request
Responses
- 200
- 401
- 403
- 404
- 502
The account's contacts, relayed verbatim from the ops-service. No envelope; see above.
Authentication failed: the X-API-Token header was missing, malformed,
expired or not recognised.
This response is text/plain, not JSON. It is written by
http.Error in the authentication middleware, which runs before any
handler and therefore before anything that would build a JSON envelope.
A client that unconditionally JSON-parses response bodies will fail on
this one, so check the status code first.
The token is valid, but it is not allowed to act on this tenant.
An API token is minted inside one tenant and stays bound to it for life.
Sending it to a path whose tenant segment names a different tenant is
refused here, in middleware, before the operation runs, so this says
nothing about the resource you asked for, only about which tenant the
path named. Check the tenant server variable against the console the
token was created in.
No tenant matches the tenant segment of the request path. An AWS account that does not exist is not a 404; it is a 502, like every other upstream outcome.
The contacts could not be read. This one status covers everything that
can go wrong past Prism's own routing: the ops-service is unreachable
or timed out; this self-hosted install is not paired with CloudKeeper
SaaS; the account does not exist; the account is not one this tenant's
payer can read; AWS refused. message and error both carry the
upstream reason verbatim and are the only way to tell these apart.
Unlike the 200, this response is a normal error envelope.