Docs

Build an integration

Pull Pbrize materials into Blender, Unity, Unreal or Godot — browse the library, download channels, and submit generations without leaving the tool. Everything below is served from /api/v1; the full schema lives in the interactive reference.

Authentication

Every endpoint (except the connect exchange) authenticates with an API key sent as a bearer token. Keys look like pbrz_…, are shown once at creation, and can be revoked anytime from account settings.

GET /api/v1/textures
Authorization: Bearer pbrz_<secret>

The connect flow (recommended)

Plugins obtain a key without any copy-paste using a loopback redirect — the same pattern CLI tools like gcloud use:

  1. Start a one-shot HTTP listener on 127.0.0.1 on a random free port (1024–65535), generate a random state value, and open the user's browser at:
https://pbrize.com/integrations/connect?state=<random-state>&port=<port>&client=blender
  1. The user logs in (if needed) and approves the request. Pbrize then redirects the browser to your listener with a one-time code:
http://127.0.0.1:<port>/?code=pbrzc_<one-time-code>&state=<random-state>
  1. Verify state matches what you generated, then exchange the code within 60 seconds (codes are single-use):
POST /api/v1/connect/exchange
Content-Type: application/json

{ "code": "pbrzc_<one-time-code>" }

→ 200
{
  "apiKey": "pbrz_<secret>",
  "keyId": "key_…",
  "user": { "id": "…", "email": "[email protected]", "name": "You" }
}

Store the returned apiKey in your plugin's preferences. If the user denies the request, the redirect carries an error instead:

http://127.0.0.1:<port>/?error=access_denied&state=<random-state>

Query parameters in the redirect are form-encoded (spaces become +) — decode state with form semantics before comparing.

Fallback for headless machines or restrictive firewalls: the user creates a key manually under account settings → API keys and pastes it into the plugin.

Endpoints

POST/api/v1/connect/exchange
Exchange a one-time connect code for an API key
GET/api/v1/me
Identity and coin balance
GET/api/v1/textures
Paginated texture library with search
GET/api/v1/textures/:id
Texture detail with per-channel content versions
POST/api/v1/textures/:id/download
Presigned download URLs per channel
POST/api/v1/uploads/reference
Presigned upload for a generation reference image
POST/api/v1/generations
Submit a base texture generation
POST/api/v1/textures/:id/pbr-channels
Generate PBR channels for an existing texture
GET/api/v1/generations/:taskId
Poll generation status

Generation is two explicit stages mirroring the product: submit a base texture via POST /api/v1/generations, poll until it succeeds, then request PBR channels for the resulting texture. Each stage debits coins through the normal workflow lifecycle — failures report their refund status in the task status payload.

Engine semantics (semantics.json)

The @pbrize/integrations package ships a generated semantics.json artifact describing per-channel color spaces, normal-map conventions, and material wiring for engines with a designed plugin — Blender today (which input each channel feeds, and which adapter nodes — normal map, bump, AO multiply — to insert). Vendor it at build time; don't fetch it at runtime. Cache downloaded channels by texture id plus each channel's version value from the detail and download endpoints — channel content changes under a stable texture id, and the version changes exactly when the content does.

Rate limits and errors

Requests are limited per key (burst-friendly token bucket, ~60/min). Exceeding it returns HTTP 429 with a Retry-After header. All errors use one envelope:

{ "error": { "code": "rate_limited", "message": "…" } }