Windpaint
Account

Organizations and projects

How your organization, team roles and projects fit together, and how a request decides which project it acts in.

Your organization owns everything billable and shared: credits, members, API keys and webhooks. Inside it, projects keep work apart. Every generation job, asset and product run belongs to exactly one project, and every organization starts with a project called Default.

# Generate into a specific project by slug
curl -X POST https://api.windpaint.ai/v1/generation/capabilities/image.generate \
  -H "Authorization: Bearer $WINDPAINT_API_KEY" \
  -H "X-Windpaint-Project: campaign-q4" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "a ceramic teapot on a linen tablecloth, soft window light"}'

Organizations

An organization is created for you when you sign up (email and password with email confirmation, Google, or GitHub). Windpaint is in early access, so a new account waits on the waitlist until it’s approved; approval grants 200 free credits that expire after 30 days. See Billing.

Each user belongs to one organization. The organization holds:

  • The credit balance. Credits are org-wide; every project spends from the same balance.
  • Members and their roles.
  • API keys and account webhooks.
  • Projects, and through them every job, asset and run.

Members and roles

Each member has one role. The four roles are fixed; you can’t define your own.

RoleSummary
ownerEverything. The person who signed up is the owner.
adminMembers, API keys, webhooks, organization settings, projects, generation and billing.
memberGenerates and reads. Can see projects, billing and their own API keys, but can’t create keys or change settings.
read_onlyReads everything a member can, plus webhooks. Can’t generate.

What each role can do, by permission:

ActionPermissionowneradminmemberread_only
Submit, cancel and upload (generation, products)generation:write✓✓✓
View jobs, assets, runs, modelsgeneration:read✓✓✓✓
View projectsprojects:read✓✓✓✓
Create, rename and archive projectsprojects:write✓✓
View balance, statement, usagebilling:read✓✓✓✓
Buy credits, set the low-balance thresholdbilling:write✓✓
List your own API keysapi_keys:read✓✓✓✓
Create and edit API keysapi_keys:create✓✓
Revoke API keysapi_keys:revoke✓✓
View webhookswebhooks:read✓✓✓
Create, edit and delete webhookswebhooks:create / update / delete✓✓
View membersusers:read✓✓✓✓
Invite, change roles, remove membersusers:create / update / delete✓✓
Edit organization settingsorgs:update✓✓

A request without the permission it needs gets a 403. See Authentication for the response body.

You can’t hand out more access than you hold. An admin can’t promote someone to owner, and can’t create an API key bound to the owner role.

Inviting your team

Invites are managed in the dashboard.

Open Settings → Team

In the dashboard, go to Settings → Team and choose Invite. You need the owner or admin role.

Pick the email and role

Enter the person’s email and pick admin, member or read_only. Pick the smallest role that does the job; you can change it later.

They accept

Windpaint emails an invitation link that is valid for 14 days. If it expires or gets lost, resend it from the same page; resending invalidates the previous link.

From Settings → Team you can also change a member’s role or remove them. Removing a member deactivates their account, so their API keys stop working on the next request. Rotate any automation that depended on them before you remove them.

Membership changes fire account webhook events: member.invited, member.joined, member.role_changed and member.removed.

Projects

A project is a container for jobs, assets and runs. Use one per app, environment, client or campaign; nothing is shared between projects except the credit balance.

  • Default project. Every organization has one, named “Default” with the slug default. It’s used whenever a request doesn’t name a project. It can’t be archived.
  • Slugs. Each project has a slug that you can use anywhere a project id is accepted. Slugs are 1 to 64 characters of lowercase letters, digits and hyphens, and can’t start or end with a hyphen. If you don’t pass one, it’s derived from the name ("Campaign Q4" becomes campaign-q4). Slugs are unique within your organization; a taken slug returns 409.
  • Archiving. Archiving a project makes it read-only. Its jobs and assets stay readable, but any write into it (submitting a job, uploading, starting a product run) returns 409 with "The project is archived.". There’s no unarchive today.
  • Assets across projects. A job’s inputs must be assets in the same project. GET /v1/generation/assets/{id} reads an asset from any project in your organization.

Creating a project

curl
curl -X POST https://api.windpaint.ai/v1/projects \
  -H "Authorization: Bearer $WINDPAINT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Campaign Q4", "description": "Holiday product shots"}'
{
  "data": {
    "id": "5b0f6c1e-8d2a-4f3b-9e71-0c4d2a9b7e15",
    "organization_id": "c3a1e8f2-6b4d-4e0a-8f1c-2d7b9e5a1c33",
    "name": "Campaign Q4",
    "slug": "campaign-q4",
    "description": "Holiday product shots",
    "is_default": false,
    "is_archived": false,
    "created_by": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
    "created_at": "2026-10-04T14:12:09.481220Z",
    "updated_at": null,
    "archived_at": null
  }
}

You can also create, rename and archive projects in the dashboard under Settings → Projects. The full endpoint list is in the Projects API reference.

Which project a request uses

Every request that reads or writes jobs, assets or runs resolves one project, in this order:

  1. project_id in the request body (generation submits, estimates and product runs). Accepts an id or a slug.
  2. The X-Windpaint-Project header. Accepts an id or a slug.
  3. Your organization’s default project.

The first one present wins; they aren’t merged. A project that doesn’t exist in your organization returns 404. List endpoints such as GET /v1/generation/requests and GET /v1/generation/assets only return items from the resolved project, so send the header on reads too.

GET /v1/generation/requests/{id}/status and GET /v1/generation/assets/{id} find the item anywhere in your organization, so polling a job doesn’t need the header.

The dashboard’s project switcher sends X-Windpaint-Project for you.

Selecting a project in the CLI

The CLI saves a default project in its config file and sends it as X-Windpaint-Project on every command:

windpaint projects                      # list; * marks the selected one
windpaint projects select campaign-q4   # save by slug or id
windpaint projects select --clear       # go back to the default project

A --project flag or the WINDPAINT_PROJECT environment variable overrides the saved project for one command or one shell. See CLI configuration.

Next steps