GetItDoneGetItDone Docs

Create an API key

POST
/v1/api-keys

Mints a new org-owned API key. Beyond the api-keys:manage scope check, the CALLING credential's creator must currently hold an owner/admin membership in the organization — a key minted while its creator was an admin stops being able to mint further keys the moment that user is demoted (403 insufficient_scope). Supports the optional Idempotency-Key header; note the replay caution: a replayed response includes the ORIGINAL plaintext key again within the 24h replay window (the same tradeoff Stripe makes for idempotent secret-bearing responses) — treat a stored Idempotency-Key as equally sensitive to the secret itself.

Authorization

bearerAuth
headerAuthorizationBearer <token>

A gid_ API key (Profile → API Keys) or an OAuth 2.1 access token.

Header Parameters

Idempotency-Key?string

Optional client-generated key (1-255 visible ASCII characters; a UUID works) making this POST safely retryable. Retrying with the SAME key and byte-identical body within 24h replays the stored first response (marked Idempotency-Replayed: true, never re-executed, never charged against quota). The same key with a different body answers 422 idempotency_key_reused; a retry racing the first execution answers 409 idempotency_in_progress. Omitting the header executes normally with no idempotency guarantee.

Length1 <= length <= 255

Request Body

application/json
  1. body

Fields for minting a new API key.

name*string

Caller-given label for the key.

Length1 <= length <= 200
scopes?array<>

Subset of scopes to grant. Defaults to every scope EXCEPT api-keys:manage — key-minting is never granted by default and must be requested explicitly.

test_mode?boolean

Mint a gid_test_… sandbox-prefixed key instead of a live one.

expires_in_days?integer

Expiry in days from now (1-365). Omit for no expiry.

Range1 <= value <= 365

Response Body

The created key, with its plaintext secret shown once.

application/json
  1. response

A freshly minted API key, including its one-time plaintext secret.

id*string

Stable id of the key row.

name*|

Caller-given label.

key_prefix*|

Non-secret fingerprint prefix shown in key lists (e.g. gid_ab12); never the full secret.

scopes*array<>

Scopes granted to this key.

last_used_at*|

Last time this key authenticated a request, or null.

expires_at*|

Expiry time, or null when the key never expires.

created_at*string

ISO-8601 UTC.

Match^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
Formatdate-time
legacy*boolean

True for a pre-migration user-owned key; false for a current org-owned key. Legacy keys are read-only here — mint new keys as non-legacy.

key*string

The plaintext secret — shown EXACTLY ONCE. Store it now; it cannot be retrieved again.

Example Request
curl -X POST 'https://app.nowgetitdone.com/v1/api-keys' \  -H 'Content-Type: application/json' \  -d '{  "name": "CI deploy bot"}'
Example Response
{  "id": "string",  "name": "string",  "key_prefix": "string",  "scopes": [    "workspaces:read"  ],  "last_used_at": "2019-08-24T14:15:22Z",  "expires_at": "2019-08-24T14:15:22Z",  "created_at": "2019-08-24T14:15:22Z",  "legacy": true,  "key": "gid_51f3...redacted"}