Sign-up
Public registration, invitations and onboarding.
| Operation | Method and path |
|---|---|
| Get public sign-up configuration | GET /v1/signups/config |
| Get a proof-of-work challenge | GET /v1/signups/challenge |
| Join the waitlist | POST /v1/waitlist |
| Confirm a waitlist email address | POST /v1/waitlist/confirm |
| Preview an invitation | GET /v1/invites/{code} |
| Accept an invitation and start sign-up | POST /v1/invites/{code}/accept |
| Begin public sign-up | POST /v1/signups |
| Get onboarding progress | GET /v1/me/onboarding |
| Update onboarding progress | PATCH /v1/me/onboarding |
Get public sign-up configuration
Section titled “Get public sign-up configuration”GET /v1/signups/configReturns the current access mode, legal versions, consent copy, billing state and available plans.
- Operation:
getSignupConfig - Scopes: none (public)
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
Sign-up configuration. | SignupConfig |
Errors: 500, as problem+json with a stable code.
Example
curl https://api.guv.dev/v1/signups/config \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "mode": "string", "waitlist_open": false, "invite_required": false, "data_location": "string", "terms": { "version": "string", "url": "string" }, "privacy": { "version": "string", "url": "string" }, "waitlist_consent": { "version": "string", "text": "string" }, "billing_enabled": false, "proof_of_work": { "difficulty_bits": 1 }, "plans": [ { "id": "string", "name": "string", "price": { "amount": "7.42", "currency": "GBP", "display": "£7.42" }, "card_required": false } ]}Get a proof-of-work challenge
Section titled “Get a proof-of-work challenge”GET /v1/signups/challengeSolve SHA-256(challenge + “:” + decimal nonce) until the digest has at least difficulty_bits leading zero bits. The signed challenge expires after ten minutes and each successful solution can be used once.
- Operation:
getSignupChallenge - Scopes: none (public)
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
Proof-of-work challenge. | SignupChallenge |
Errors: 500, as problem+json with a stable code.
Example
curl https://api.guv.dev/v1/signups/challenge \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "challenge": "string", "algorithm": "string", "difficulty_bits": 1, "expires_at": "2026-10-22T13:05:00Z"}Join the waitlist
Section titled “Join the waitlist”POST /v1/waitlistSends a double opt-in confirmation email. The response is identical for new and existing entries.
- Operation:
joinWaitlist - Scopes: none (public)
- Idempotency-Key: optional
Request body (application/json, required): WaitlistJoinRequest
| Field | Type | Description |
|---|---|---|
email * |
string (email) | |
name |
string | |
building |
string | |
heard_from |
string | |
consent * |
boolean | |
consent_version * |
string | |
website |
string | |
pow |
SignupPow |
Responses
| Status | Meaning | Body |
|---|---|---|
202 Accepted |
Confirmation email queued. | WaitlistJoinAccepted |
Errors: 400, 422, 429, 500, as problem+json with a stable code.
Example
curl -X POST https://api.guv.dev/v1/waitlist \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "email": "ada@example.co.uk", "name": "string", "building": "string", "heard_from": "string", "consent": false, "consent_version": "string", "website": "string", "pow": { "challenge": "string", "nonce": "string" }}'Example response
{ "status": "pending_confirmation", "message": "string"}Confirm a waitlist email address
Section titled “Confirm a waitlist email address”POST /v1/waitlist/confirmConfirms the address using the single-use token sent by email. Repeating a valid confirmation is safe.
- Operation:
confirmWaitlist - Scopes: none (public)
- Idempotency-Key: optional
Request body (application/json, required): WaitlistConfirmRequest
| Field | Type | Description |
|---|---|---|
token * |
string |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
Address confirmed. | WaitlistConfirmed |
Errors: 400, 410, 422, 429, 500, as problem+json with a stable code.
Example
curl -X POST https://api.guv.dev/v1/waitlist/confirm \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "token": "string"}'Example response
{ "status": "confirmed"}Preview an invitation
Section titled “Preview an invitation”GET /v1/invites/{code}Checks the invitation code without revealing the bound email address.
- Operation:
getInvite - Scopes: none (public)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
code * |
path | string |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
Invitation preview. | InvitePreview |
Errors: 403, 404, 409, 410, 429, 500, as problem+json with a stable code.
Example
curl https://api.guv.dev/v1/invites/code \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "status": "valid", "email_hint": "string", "expires_at": "2026-10-22T13:05:00Z"}Accept an invitation and start sign-up
Section titled “Accept an invitation and start sign-up”POST /v1/invites/{code}/acceptStarts email verification using the invitation code as the abuse barrier.
- Operation:
acceptInvite - Scopes: none (public)
- Idempotency-Key: optional
Parameters
| Name | In | Type | Description |
|---|---|---|---|
code * |
path | string |
Request body (application/json, required): InviteAcceptRequest
| Field | Type | Description |
|---|---|---|
email * |
string (email) | |
name |
string | |
workspace_name |
string | |
accept_terms * |
boolean | |
terms_version * |
string | |
privacy_version * |
string | |
website |
string |
Responses
| Status | Meaning | Body |
|---|---|---|
202 Accepted |
Email verification started. | SignupStarted |
Errors: 400, 403, 404, 409, 410, 422, 429, 500, as problem+json with a stable code.
Example
curl -X POST https://api.guv.dev/v1/invites/code/accept \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "email": "ada@example.co.uk", "name": "string", "workspace_name": "string", "accept_terms": false, "terms_version": "string", "privacy_version": "string", "website": "string"}'Example response
{ "signup_id": "string", "verification_id": "string", "email": "string", "expires_at": "2026-10-22T13:05:00Z", "next": "verify_email"}Begin public sign-up
Section titled “Begin public sign-up”POST /v1/signupsChecks legal acceptance, email, invite mode and proof of work, then sends the existing email verification code. For proof of work solve SHA-256(challenge + “:” + decimal nonce) for the configured leading zero bits.
- Operation:
beginSignup - Scopes: none (public)
- Idempotency-Key: optional
Request body (application/json, required): SignupBeginRequest
| Field | Type | Description |
|---|---|---|
email * |
string (email) | |
name |
string | |
workspace_name |
string | |
invite_code |
string | |
accept_terms * |
boolean | |
terms_version * |
string | |
privacy_version * |
string | |
marketing_opt_in |
boolean | |
website |
string | |
pow |
SignupPow |
Responses
| Status | Meaning | Body |
|---|---|---|
202 Accepted |
Email verification started. | SignupStarted |
Errors: 400, 403, 404, 409, 410, 422, 429, 500, as problem+json with a stable code.
Example
curl -X POST https://api.guv.dev/v1/signups \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "email": "ada@example.co.uk", "name": "string", "workspace_name": "string", "invite_code": "string", "accept_terms": false, "terms_version": "string", "privacy_version": "string", "marketing_opt_in": false, "website": "string", "pow": { "challenge": "string", "nonce": "string" }}'Example response
{ "signup_id": "string", "verification_id": "string", "email": "string", "expires_at": "2026-10-22T13:05:00Z", "next": "verify_email"}Get onboarding progress
Section titled “Get onboarding progress”GET /v1/me/onboardingReturns plan, legal acceptance and checklist progress for the signed-in human user.
- Operation:
getMyOnboarding - Scopes: any signed-in principal
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
Onboarding state. | Onboarding |
Errors: 401, 403, 500, as problem+json with a stable code.
Example
curl https://api.guv.dev/v1/me/onboarding \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "workspace_id": "string", "plan": "trial", "plan_chosen": false, "trial_ends_at": "2026-10-22T13:05:00Z", "card": { "required": false, "status": "not_required", "setup_url": "https://guv.dev/" }, "legal": { "terms_version": "string", "privacy_version": "string", "accepted_terms_version": "string", "accepted_privacy_version": "string", "needs_acceptance": false }, "checklist": [ { "id": "create_project", "title": "string", "description": "string", "status": "pending", "source": "auto", "completed_at": "2026-10-22T13:05:00Z" } ], "completed_count": 1, "total_count": 1, "complete": false, "dismissed": false, "version": 1}Update onboarding progress
Section titled “Update onboarding progress”PATCH /v1/me/onboardingChoose a plan, accept current legal versions, dismiss onboarding or update manual checklist steps.
- Operation:
updateMyOnboarding - Scopes: any signed-in principal
- Idempotency-Key: required
- Concurrency: send the
ETagyou read asIf-Match
Request body (application/json, required): OnboardingUpdate
| Field | Type | Description |
|---|---|---|
plan |
trial, hobby, pro, business, dedicated |
|
accept_legal |
object | |
dismissed |
boolean | |
steps |
array of object |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
Updated onboarding state. | Onboarding |
Errors: 400, 401, 403, 409, 412, 422, 429, 500, as problem+json with a stable code.
Example
curl -X PATCH https://api.guv.dev/v1/me/onboarding \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "plan": "trial", "accept_legal": { "terms_version": "string", "privacy_version": "string" }, "dismissed": false, "steps": [ { "id": "create_project", "status": "complete" } ]}'Example response
{ "workspace_id": "string", "plan": "trial", "plan_chosen": false, "trial_ends_at": "2026-10-22T13:05:00Z", "card": { "required": false, "status": "not_required", "setup_url": "https://guv.dev/" }, "legal": { "terms_version": "string", "privacy_version": "string", "accepted_terms_version": "string", "accepted_privacy_version": "string", "needs_acceptance": false }, "checklist": [ { "id": "create_project", "title": "string", "description": "string", "status": "pending", "source": "auto", "completed_at": "2026-10-22T13:05:00Z" } ], "completed_count": 1, "total_count": 1, "complete": false, "dismissed": false, "version": 1}