Merchant profiles
Select, create, activate and prepare a connected sandbox merchant for a club.
Finance at /sell?club=<uuid> lists locally registered PostgreSQL profiles already used by a
club in the selected club's owner space, not all Stripe accounts or profiles belonging to another
space. Each club selects one merchant; clubs in the same space may share it. Replacement is outside
this flow. Merchant operations require an authenticated administrator of the selected club.
query MerchantProfiles($clubId: ID!) {
merchantProfiles(clubId: $clubId) {
selectedMerchantId
profiles {
id
name
email
country
entityType
legalForm
environment
platformAccountId
stripeAccountId
configurationStatus
paymentsEnabled
payoutsEnabled
checkedAt
catalogReady
}
}
}Required clubId: ID! is a local club UUID. MerchantProfiles! contains nullable
selectedMerchantId: ID and profiles: [MerchantProfile!]!. No search, filters, sorting
or pagination arguments are accepted. Profiles are ordered by name and local ID. A profile that is
unused or used only by a club in another owner space is not returned as a suggestion,
and selectMerchant refuses it like an unknown profile.
Profile fields
| Fields | Types | Meaning |
|---|---|---|
id | ID! | Local profile ID used for selection; never send an account ID instead. |
name, email, country | String! | Merchant identity; country is a two-letter uppercase code. |
entityType | String! | company, individual, non_profit or government_entity. |
legalForm | String | Optional legal form, e.g. SAS, separate from Stripe entity type. |
environment, platformAccountId, stripeAccountId | String! | Sandbox and Stripe account identity. |
configurationStatus | String! | pending (configuration to complete) or ready. |
paymentsEnabled, payoutsEnabled | Boolean! | Separate payment and payout capability state. |
checkedAt | String | Nullable last verification timestamp. |
catalogReady | Boolean! | Whether the connected three-offer catalogue is prepared. |
Select and create
mutation SelectMerchant($clubId: ID!, $merchantProfileId: ID!) {
selectMerchant(clubId: $clubId, merchantProfileId: $merchantProfileId) {
id
configurationStatus
}
}
mutation CreateMerchant($input: CreateMerchantInput!) {
createMerchant(input: $input) {
id
name
configurationStatus
paymentsEnabled
payoutsEnabled
catalogReady
}
}Both return MerchantProfile!. Selection validates local UUIDs, club/profile existence,
matching sandbox/platform and compatible Stripe account configuration. A club with a
different selected merchant is rejected. An incomplete profile is selectable to finish
activation, and selection by another club does not exclude it.
CreateMerchantInput requires clubId: ID!, requestId: ID!, name: String!,
email: String!, country: String!, entityType: String!; legalForm: String is optional.
Use valid UUIDs, a nonblank name of at most 200 characters, an email of at most 254
characters with a local part and dotted domain, a two-letter uppercase country code,
a supported entity type and legal form of at most 100 characters. Keep the request UUID
stable for retries of the exact same input.
Creation provisions Accounts v2, saves the local profile and selects it for the club.
French platforms require account tokens for merchant identity. This sandbox-only
implementation creates a v2 account token with the test secret key, passes country
outside the token, and leaves agreement acceptance to Stripe-hosted onboarding.
Merchant configuration uses a full dashboard, Stripe fees paid by the merchant and losses
handled by Stripe. Live mode is rejected. Errors are returned through GraphQL.
The seeded Ukab Clubs sandbox fixture is intentionally different: bootstrap creates it without a dashboard, accepts test terms and identity data, and leaves requirement, fee and loss responsibility with the platform. Runtime accepts that configuration only with the exact versioned fixture metadata; it does not change merchants created by this mutation.
Activate, verify and prepare
mutation MerchantOnboarding($clubId: ID!) {
merchantOnboarding(clubId: $clubId)
}
mutation RefreshMerchant($clubId: ID!) {
refreshMerchant(clubId: $clubId) {
id
configurationStatus
paymentsEnabled
payoutsEnabled
checkedAt
catalogReady
}
}
mutation PrepareMerchantCatalog($clubId: ID!) {
prepareMerchantCatalog(clubId: $clubId) {
id
catalogReady
}
}Each requires the club UUID and an existing selected merchant on the configured platform.
merchantOnboarding returns a non-null Stripe-hosted activation URL (String!). After
returning, Settings automatically synchronizes capabilities. It also synchronizes the selected
merchant every minute while visible. refreshMerchant and
prepareMerchantCatalog return MerchantProfile!. Preparation can be resumed/retried and
verifies the three connected Product/Price mappings shared by clubs selecting this merchant.
Checkout requires enabled payments and a valid catalogue; payouts are displayed separately.
The UI invalidates merchant, invoice and affected offer caches after these operations.