Submit Distribution Form
Public endpoint for end users to claim a pass through a published distribution. It finds or creates a client for the submitter, issues (or reuses) their pass, emails the wallet download links, and returns those links along with a short-lived client token.
Auth: Public — no Bearer token, no workspace membership.
Submit
POST /wallethero-api/distribution/submit
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
distribution_id | string (UUID) | Yes | Target distribution. Must reference a distribution whose status is published. |
email | string (email) | Yes | Submitter's email address. Must be a valid email. |
first_name | string | Yes | Submitter's first name (min 1 character). |
last_name | string | No | Submitter's last name. |
phone | string | No* | Submitter's phone number (trimmed, max 50 characters). Top-level field, not a custom field — this is what the server checks when the distribution's form_fields_config marks phone required, and what it matches returning clients on (email-or-phone). A phone sent only as custom_fields.phone is still accepted and promoted, but send it here. |
marketing_consent | boolean | No* | Whether the submitter opted into marketing. *Must be true when the distribution's form_fields_config marks the consent checkbox required — enforced server-side. When set, the server also stamps consent provenance on the client (marketing_consent_at, marketing_consent_source: "distribution_form" / "embed_form", and marketing_consent_text — a snapshot of the consent label from form_fields_config). |
custom_fields | object (Record<string, any>) | No | Custom field values, keyed by field name (should match the distribution's form_fields_config). |
referral_code | string | No | Referral code of the inviting client. Trimmed; max 20 characters. Only attributed for brand-new clients. |
Example Request
bash
curl -X POST "https://api.wallethero.app/wallethero-api/distribution/submit" \
-H "Content-Type: application/json" \
-d '{
"distribution_id": "b7f0c9d2-1a3e-4c8b-9f2d-7e6a5c4b3a21",
"email": "[email protected]",
"first_name": "Jane",
"last_name": "Customer",
"phone": "+15551234567",
"marketing_consent": true,
"custom_fields": { "birth_date": "1990-04-17" },
"referral_code": "FRIEND10"
}'Response (200) — New Pass
json
{
"success": true,
"isResend": false,
"message": "Pass created successfully. Check your email for download links.",
"data": {
"pass_id": "9c1e2d3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
"apple_pass_url": "https://passes.wallethero.app/apple/pass/9c1e2d3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f?token=1f6d0a9c2b7e4d8f0a3c5e7b9d1f3a5c",
"google_pass_url": "https://passes.wallethero.app/google/pass/9c1e2d3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f?token=1f6d0a9c2b7e4d8f0a3c5e7b9d1f3a5c",
"client_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}Response (200) — Existing Pass Resent
When the submitter already has a pass for the distribution's project, the existing pass is reused and the email is resent.
json
{
"success": true,
"isResend": true,
"message": "Your pass already exists! We've resent the download links to your email.",
"data": {
"pass_id": "9c1e2d3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
"apple_pass_url": "https://passes.wallethero.app/apple/pass/9c1e2d3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f?token=1f6d0a9c2b7e4d8f0a3c5e7b9d1f3a5c",
"google_pass_url": "https://passes.wallethero.app/google/pass/9c1e2d3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f?token=1f6d0a9c2b7e4d8f0a3c5e7b9d1f3a5c",
"client_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}Response Fields
| Field | Type | Description |
|---|---|---|
success | boolean | Always true on success. |
isResend | boolean | true when an existing pass was reused and re-emailed instead of created. |
message | string | Human-readable status message (varies by isResend). |
data.pass_id | string (UUID) | Created or existing pass identifier. |
data.apple_pass_url | string (URL) | Apple Wallet download URL. Includes a per-pass ?token= when PASS_DOWNLOAD_TOKEN_SECRET is configured; passserver requires it unless it runs with PASS_DOWNLOAD_REQUIRE_TOKEN=false. |
data.google_pass_url | string (URL) | Google Wallet save URL. Includes the same per-pass ?token=. |
data.client_token | string (JWT) | Short-lived loyalty-portal token for deep-linking. May be omitted if generation fails. Do not persist it. |
Errors
| Status | Code | Description |
|---|---|---|
400 | INVALID_PAYLOAD | Body fails validation, distribution_id / pass_template_id not found, or a field marked required in the distribution's form_fields_config is missing (Missing required field(s): …) — including a required marketing-consent checkbox that was not affirmatively checked. referral_code is exempt: malformed codes are dropped, never rejected. |
403 | FORBIDDEN | Distribution exists but is not published. |
SDK
No SDK method matches this exact path. The SDK's PublicDistributionService.enroll() posts to the token-based /embed/distribution/:token/submit endpoint (documented separately). For this endpoint, call the REST endpoint directly.