Skip to content
GenAff

Quickstart and API reference

GenAff is an OpenAI-compatible gateway. The web app manages your session; your own code uses a GenAff key on a separate plane. The two credentials are never mixed.

Contract 1.1.1 · Phase 1

Two planes

Dashboard and gateway authentication planes
PlanePathCredentialUsed by
Dashboard/api/v1/*Bearer <session JWT>This web app
Gateway/v1/*Bearer gk_live_…Your server or SDK

Quickstart

  1. 1. Create an account and verify your email.

    The verification token arrives in the URL fragment. This page clears it from the address bar after reading it. You cannot sign in until the email is verified.

  2. 2. Connect a provider.

    Paste the provider's own API key. GenAff validates it with the provider before storing it encrypted. One connection per provider; use Replace to change it.

  3. 3. Create a GenAff gateway key.

    The plaintext gk_live_… is shown once. Store it on your server; this dashboard never receives it again.

  4. 4. List the models available to you.

    curl / models
    export GENAFF_API_KEY="gk_live_YOUR_KEY"
    
    curl https://api.genaff.cloud/v1/models \
      -H "Authorization: Bearer $GENAFF_API_KEY"
  5. 5. Make a non-streaming chat request.

    Copy a model ID from the Models page. Phase 1 rejects stream: true and unsupported fields; nothing is silently dropped.

    curl / chat/completions
    curl https://api.genaff.cloud/v1/chat/completions \
      -H "Authorization: Bearer $GENAFF_API_KEY" \
      -H "content-type: application/json" \
      -d '{
        "model": "provider:upstream-model",
        "messages": [{"role": "user", "content": "What is a merkle tree?"}],
        "max_tokens": 128,
        "stream": false
      }'

Providers

Only providers with an adapter and passing contract tests are listed. The landing page reads the enabled set from the public provider endpoint; the dashboard reads the authenticated set. Capabilities are an open map — do not hardcode the full key set.

One credential per provider

A second create for the same provider returns 409 CONNECTION_EXISTS. Use Replace credential instead of adding another connection.

Model IDs

IDs use provider_code:upstream_model_id. Only the first colon is a delimiter. Inside the upstream part, these characters are escaped so the ID is URL-path safe:

Model ID escape sequences
CharacterEncoding
~~~
:~C
%~P
?~Q
#~H
space~S

Slashes and dots are preserved. Never construct an ID yourself; copy it from the Models page or /v1/models.

Chat

Messages accept system, user and assistant roles with string content. Supported fields include temperature, top_p, one of max_tokens or max_completion_tokens, stop and n=1. Tools, response_format, logprobs, penalties, seed, user and images are rejected.

No streaming

Phase 1 chat is request/response only. Send stream: false. There is no SSE endpoint and no browser chat UI.

Rate limits

Every bucket returns 429 RATE_LIMITED with a Retry-After header. The backend sends seconds; the web client also accepts an HTTP-date. Do not retry in a tight loop.

Rate-limit buckets
ActionBucket
register20/hour per IP
verify-email60/hour per IP
resend verification5/hour per IP and email
login20/5 min per IP · 10/5 min per email
refresh60/min per IP
create key20/hour per account
GET /v1/models120/min per gateway key
POST /v1/chat/completions60/min per gateway key

Error reference

Every non-2xx response uses the same envelope. Switch on error.code, never on the message. The request ID is echoed in x-request-id and should be included in support tickets.

GenAff error codes and actions
CodeHTTPWhat it means
BAD_REQUEST400

Request rejected

The request failed.

VALIDATION_ERROR422

Check the highlighted field

The request failed.

PASSWORD_POLICY_VIOLATION400

Choose a stronger password

Use at least 12 characters, avoid common passwords, and do not include your email address.

INVALID_VERIFICATION_TOKEN400

Verification link unusable

The link may be expired, already used, or malformed. Request a new one.

INVALID_CREDENTIALS401

Email or password is incorrect

Password recovery is not available in Phase 1. Contact support if you are locked out.

UNAUTHORIZED401

Sign in to continue

The dashboard uses a short-lived access token. A GenAff API key (gk_live_…) belongs on the gateway plane, not /api/v1.

INVALID_REFRESH_TOKEN401

Your session ended

Sign in again. The old session cannot be reused.

REFRESH_TOKEN_REUSED401

Session revoked for security

A rotated refresh token was replayed. Every session in that family was revoked.

INVALID_API_KEY401

GenAff API key rejected

The gateway uses a GenAff API key (gk_live_…). A dashboard JWT belongs on /api/v1, not /v1.

EMAIL_NOT_VERIFIED403

Verify your email first

Request a new verification link if the original one expired.

ACCOUNT_SUSPENDED403

Account suspended

Contact support to resolve the account state.

FORBIDDEN403

Request rejected

The request failed.

NOT_FOUND404

Not found

The resource may have been removed, or it belongs to another account.

MODEL_NOT_FOUND404

Model unavailable

Refresh the connection's models or choose a model from the current list.

METHOD_NOT_ALLOWED405

Request rejected

The request failed.

CONNECTION_EXISTS409

Provider already connected

GenAff allows one connection per provider. Replace the existing credential instead.

PROVIDER_UNSUPPORTED400

Provider not available

Choose a provider from the supported list.

PROVIDER_CREDENTIAL_INVALID400

Provider rejected this credential

Check the key with the provider, then paste it again. Nothing was stored.

PROVIDER_UNAVAILABLE502

Provider unavailable

Nothing was stored or changed. Try again in a moment.

UNSUPPORTED_PARAMETER400

Unsupported parameter

Phase 1 accepts a bounded OpenAI-compatible subset. Remove the named field.

UPSTREAM_AUTH_FAILED502

Provider credential was rejected

Re-check or replace the stored credential for this provider.

UPSTREAM_INVALID_REQUEST400

Provider rejected the request

Adjust the request parameters. GenAff does not silently drop unsupported fields.

UPSTREAM_QUOTA_EXCEEDED402

Provider quota exhausted

Your upstream provider account has no credit. GenAff does not bill you for inference — top up with that provider, then retry.

UPSTREAM_RATE_LIMIT429

Provider rate limit

Wait for the countdown, then retry. Do not send a burst of requests.

UPSTREAM_TIMEOUT504

Provider timed out

The provider was too slow. Retry only when you intend to make another request.

UPSTREAM_ERROR502

Provider error

The upstream provider failed. Retry later.

UPSTREAM_INVALID_RESPONSE502

Provider returned unusable data

Retry once, then contact support with the request reference if it continues.

PAYLOAD_TOO_LARGE413

Request too large

Reduce the request body. GenAff accepts at most 1 MiB.

UNSUPPORTED_MEDIA_TYPE415

Request rejected

The request failed.

RATE_LIMITED429

Too many requests

Wait for the countdown before trying again.

INTERNAL_ERROR500

GenAff had a problem

Try again. If it continues, contact support with the request reference.

SERVICE_UNAVAILABLE503

GenAff had a problem

Try again. If it continues, contact support with the request reference.

Phase 1 boundary

  • No managed inference, credits or billing. Your provider account pays for usage.
  • No streaming, tool calls, structured output or image input.
  • No password reset. Contact support for recovery.
  • One connection per provider; replace, do not add.
  • No background model refresh; use the explicit Refresh models action.

Ready to try it? Create an account or sign in.