Move entries through the funnel.
One at a time, or up to 100 per call. Approving can hand the person straight to an Auth app.
1
The status graph
An entry is pending, approved or rejected. New signups land approved unless the waitlist requires review, in which case they land pending.
pending→approved|rejectedapproved⇄rejected— you can always change your mind.
Anything else is 422 Invalid status transition. Setting an entry to the status it already has is an idempotent no-op: no event, no email, no audit row.
2
Approve or reject one entry
curl -X PATCH https://api.waitlist.productcraft.co/v1/workspaces/<workspace_id>/waitlists/<waitlist_id>/entries/<entry_id> \
-H 'authorization: Bearer pcft_live_...' \
-H 'content-type: application/json' \
-d '{ "status": "approved" }'status is the only field, and only approved / rejected are accepted — you cannot push an entry back to pending. The full updated entry comes back.
The transition emits entry.approved / entry.rejected to your webhooks (chapter 6) and, if the workspace has notifications enabled, sends the matching Mail template.
3
Bulk actions
One call, up to 100 entry ids, one action. Ids are de-duped server-side and processed serially, and you get a per-row result so partial failures are visible instead of silent.
curl https://api.waitlist.productcraft.co/v1/workspaces/<workspace_id>/waitlists/<waitlist_id>/entries/bulk \
-H 'authorization: Bearer pcft_live_...' \
-H 'content-type: application/json' \
-d '{
"ids": ["150489b4-...", "72d214cd-..."],
"action": "approve"
}'{
"requested": 2,
"succeeded": 2,
"failed": 0,
"results": [
{ "id": "150489b4-...", "status": "ok" },
{ "id": "72d214cd-...", "status": "error",
"error": { "code": "...", "message": "..." } }
]
}action is approve, reject or invite-to-app. For invite-to-app you may also pass app_slug (overrides the workspace default) and send_email (default true); both are ignored for approve/reject.
4
Invite to an Auth app
The handoff: turn an approved entry into a user of your Auth consumer app, with an invite link emailed to them.
Approving does not invite automatically — invite is its own explicit action, so you can approve first and hand off later. Point the workspace at an app once:
curl -X PUT https://api.waitlist.productcraft.co/v1/workspaces/<workspace_id>/waitlist/settings \
-H 'authorization: Bearer pcft_live_...' \
-H 'content-type: application/json' \
-d '{ "default_heimdall_app_slug": "acme" }'Then invite an entry:
curl -X POST https://api.waitlist.productcraft.co/v1/workspaces/<workspace_id>/waitlists/<waitlist_id>/entries/<entry_id>/invite-to-app \
-H 'authorization: Bearer pcft_live_...' \
-H 'content-type: application/json' \
-d '{ "send_email": true }'Body is optional: app_slug overrides the workspace default for this one call, send_email (default true) controls whether the approval email goes out with the invite link baked in. With neither an app_slug nor a workspace default you get 422 Workspace has no linked Auth app.
On success the entry records invited_at and invited_to_app_slug — read those back on GET .../entries/:entry_id to see who has already been handed off, and to make a re-run of the same batch safe.
5
Reviewing the queue
Entries only arrive through the public submit endpoint — there is no admin create. To work a queue:
GET .../entries?status=pending&limit=100— cursor-paginated, returns{ data, pagination: { next_cursor, has_more } }.GET .../entries/count— total for the waitlist.GET .../entries/export.csv— streams every entry; the right tool before aDELETEof the waitlist.DELETE .../entries/:entry_id— removes one entry. Positions of the survivors are not renumbered.
6
Audit
Every status change writes a workspace audit row — rally.entry.approved / rally.entry.rejected, with the actor and the from/to statuses. Deletions record rally.entry.delete. Read them through the platform audit-log endpoint (see the Platform guides).