propgate docs

SDKkeys and members

Keys and members

Managing the credentials you are authenticating with, from the same client.

const { data, error } = await propgate.apiKeys.create({ name: "staging" });

// The only time the secret is ever readable, on this route or any other.
await writeToSecretStore(data?.key);

data?.prefix; // "pg_live_9f2a" — what every later call shows instead

Only a hash of the key is stored, so data.key is the one moment it exists in readable form anywhere. Every later call shows prefix instead — which is not a policy, it is the only thing there is to show.

propgate.apiKeys.create() is the one call this client never retries on a transport failure. It mints a key every time it is invoked, so repeating a request that may already have succeeded is a second key nobody knows about. If it returns connection_error, list your keys before trying again.

const { data } = await propgate.apiKeys.list();

for (const key of data ?? []) {
  console.log(key.name, key.prefix, key.createdBy, key.lastUsedAt, key.revoked);
}

createdBy is the address of the member the key is attributed to, or null when nobody is on record — an operator-minted key has no creator, and it inherits that honestly rather than being attributed to whoever holds it.

Rotating

// Mint the replacement first, deploy it, then revoke the old one — in that
// order, because there is no un-revoke.
const minted = await propgate.apiKeys.create({ name: "production-2026-08" });

await deploy(minted.data?.key);

const { meta } = await propgate.apiKeys.revoke(previousKeyId);

meta?.alreadyRevoked; // false if this call was the one that did it

Authenticating this call with the key you are revoking is fine — that is the rotation move, and nothing special-cases the presented key. What is refused is revoking your last active key: there is no un-revoke, so it would lock the account out of the API with no way back in. That comes back as conflict.

meta.alreadyRevoked is not a failure either way. The key is revoked when the call returns; the flag says whether this call was the one that did it, which is what a cleanup script re-running itself wants to know.

Any member of an account can revoke any of its keys. That is deliberate for now: the obvious gate — only the creator may revoke — locks an account out of a departed colleague's key at exactly the moment revoking it matters most. Doing it properly needs roles.

Members

const { data } = await propgate.members.list();

// Turns the createdBy address on a key into something you can check against.
const addresses = new Set((data ?? []).map((member) => member.email));

propgate.members.list() is read-only, and the only account call that is not about keys. A member is added exactly one way — by proving control of a mailbox through signup — and removing one needs roles, which do not exist yet.

Signing up

Not here. The first key comes from a six-digit code sent to an address, and by the time you are holding this SDK you already have a key. Use the CLI, or POST /v1/signup directly:

npx @propgate/cli signup --email you@example.com
npx @propgate/cli confirm --email you@example.com --code 123456