Skip to content

Customization

What every link inherits from your account, and what each one controls on its own.

Two different things shape a link's page, and confusing them is what makes this feel harder than it is.

Your brand is set once for the whole account and applies to every payment page you will ever serve: logo, colours, font, radius. Your link controls its own content: the images, the wording, the button, the questions asked, the languages offered, who is allowed to open it.

So the answer to "can I make this link look different from that one" is: not in its colours, yes in almost everything else.

What comes from the account, once

Logo, palette, font, corner radius and appearance mode live in Settings → Branding. Change them there and every link updates at once, alongside your hosted checkout and your invoices. The full table is on Hosted Checkout, since it is the same setting serving all three.

Branding needs a paid plan

Settings → Branding needs the Branding feature, which starts at Growth. On Pay as you go every link keeps the default appearance. Serving links from your own domain instead of wajub.link is a separate feature, Custom domain, starting at Scale.

Everything below is per link, and two links in the same account can differ on every one of them.

Images

A poster is the banner at the top of the page, and gallery holds up to ten more shown beneath it. For a product this is the difference between a page that sells and a page that states a price.

The two routes differ in what they take. The Dashboard uploads files, JPEG, PNG, GIF or WebP up to 10 MB each, and hosts them for you. The API takes URLs you already host, up to 2 048 characters each, and never uploads anything. Point them at images you serve yourself.

The button, and what follows the payment

cta_type sets the button wording from buy_now, pay, donate, register, or custom paired with your own custom_cta_text of up to 50 characters.

thank_you_message replaces the default confirmation once the payment succeeds. It is the last thing the payer reads, so it is the right place for a delivery time or a next step.

Questions for the payer

extra_fields adds inputs to the page: a table number, a size, a note for the kitchen.

A field has a name, lowercase letters, digits and underscores, a label, a type among text, email, tel, textarea, select and checkbox, a required flag, an optional placeholder, and for a select its options. A link takes up to ten fields. The page asks for the payer's email on top of them, always: a payment on a link cannot be made without one.

Two questions on the page
{
"extra_fields": [
{
"name": "size",
"label": "Size",
"type": "select",
"required": true,
"options": [
"S",
"M",
"L"
]
},
{
"name": "note",
"label": "Note to the seller",
"type": "textarea",
"required": false
}
]
}

The Dashboard checks that shape. POST /links stores extra_fields as you send it, without checking, so a field without a name or a type will not render as you expect. The answers travel with the payment, nested rather than flattened: read metadata.extra_fields.size in your webhook handler, not metadata.size.

Promo codes

A link carries up to twenty promo codes, set in the Dashboard. Each has a code, 3 to 32 uppercase letters, digits, dashes or underscores, unique across your links, a discount that is a percentage or a fixed amount, and optionally a cap on redemptions and an expiry date. The payer types the code on the page and sees the discount before paying.

Digital products

A digital product is delivered by email once the payment succeeds, so the payer must give an email address. In the Dashboard you either upload the file, from the Growth plan, or give an https URL to it, on every plan.

Languages

A link can be bilingual. supported_locales lists which of fr and en the page offers, default_locale says which one opens first, and translations carries the other version keyed by locale.

The same link, in two languages
{
"default_locale": "fr",
"supported_locales": [
"fr",
"en"
],
"translations": {
"en": {
"title": "Amina Coffee, 250 g",
"description": "Roasted in Douala, ground to order.",
"custom_cta_text": "Order now",
"thank_you_message": "Thank you, we ship within 48 hours."
}
}
}

Only four fields translate: title, description, custom_cta_text and thank_you_message. The base fields on the link are what the default locale shows, so you only ever write the second language into translations.

Currencies

supported_currencies lets the payer switch currency on the page. The link's own currency is always offered, and whatever you add joins it.

Who is allowed in

Four independent gates, and the page closes when any one of them trips.

SetThe page answers
is_public set to false404, the link is unpublished
access_passwordA password prompt before anything else is shown
max_views reached410, the view limit is spent
expiry_date past, or is_archived410, the link is over

A password-protected link asks for the password, then issues a short-lived token for that visitor. Note that a blocked attempt is not counted as a view, so the password gate does not eat into max_views.

What each type adds

The type brings its own controls, and they only exist on that type.

TypeWhat you can tune
productproduct_variants, stock, shipping, weight, and for a service the duration, location and meeting URL
eventTicket types with their own name, price and quantity, event_capacity, generate_qr_tickets, attendee_info_fields, refund_policy
fundraisingshow_progress, show_contributors, allow_overflow, impact_tiers, campaign_deadline, fundraising_milestones
donationsuggested_amounts, allow_custom_amount, min_amount, max_amount, allow_anonymous, show_donor_wall

What the API can set, and what it cannot

This is the part worth knowing before you automate anything. The API and the Dashboard do not reach the same fields, and POST /links reaches more than PUT /links/{id}.

FieldCreate via APIUpdate via APIDashboard
title, description, priceYesYesYes
currencyYesNoYes
target_amount, min_amount, max_amountYesYesYes
callback_urlYesYesNo
cta_type, custom_cta_textYesYesYes
custom_url, tagsYesYesYes
category_idBefore API version 2026-10-12Before 2026-10-12Yes
is_public, is_archived, expiry_date, sales_limitYesYesYes
accept (payment methods offered)YesYesYes
extra_fields, thank_you_messageYesNoYes
poster, galleryYes, as URLsNoYes, as uploads
Type-specific fields, event and fundraisingYesNoYes
supported_locales, default_locale, translationsNoNoYes
supported_currenciesNoNoYes
access_password, max_viewsNoNoYes
Promo codes, a digital product's fileNoNoYes
Custom domain, ticket typesNoNoYes

From API version 2026-10-12, a link has no category_id: no endpoint lists the categories it would name, so the API neither takes it on POST and PUT, nor filters GET /links on it, nor returns it. Earlier versions keep it. Versioning

In the Dashboard

Links → a link → Edit is where the whole surface lives, with a preview beside the fields. It is the only place that reaches languages, currencies, the access password, the view limit, a custom domain and event ticket types.

Each link also carries its own webhook endpoints, separate from your account-wide ones, with their own secret, a test send and a retry. Use them when one campaign needs to notify a system the rest of your account does not.

What did you think of this content?