Skip to main content

Seller onboarding

Bob needs a place for Ishtaran to send his money. Mercatto could create one for him — but instead it invites Bob to create his own, so the same identity could later work with other marketplaces too, never trapped inside Mercatto's own systems. Alice gets the same treatment.

Mercattoinvitation token"claim it withmy own email+ password"🔑Bobown AccountHolder
Bob's login belongs to Bob — Mercatto issues the invitation, but never sees his password.

Code

examples/marketplace-mercatto/seller-onboarding.ts
const bobInvitation = await mercatto.accounts.createAccountHolderInvitation(organizationId, `bob-${runId}`);
const bob = createClient();
const bobClaim = await bob.accountHolders.signUpAndClaimInvitation(bobInvitation.plainTextToken, emails.bob, STORY_PASSWORD);
const bobAccountId = (await bob.accountHolders.me()).accountId;

// Alice, the buyer, gets the identical treatment — not an "anonymous" payer.
const aliceInvitation = await mercatto.accounts.createAccountHolderInvitation(organizationId, `alice-${runId}`);
// … same claim flow …

// Mercatto's own commission lands in an Account it owns directly — no invitation needed.
const mercattoRevenueAccountId = (await mercatto.accounts.create(organizationId, `mercatto-revenue-${runId}`)).accountId;

await owner.accounts.authorizeApplication(organizationId, bobAccountId, applicationId);
await owner.accounts.authorizeApplication(organizationId, aliceAccountId, applicationId);
await owner.accounts.authorizeApplication(organizationId, mercattoRevenueAccountId, applicationId);

// DEC-037 — where does Ishtaran actually send Bob's money? Bob's own wallet, entirely outside
// Ishtaran (Mercatto never touches his private key). Mercatto's own commission, by contrast, lands
// on an address of Mercatto's OWN execution wallet — registered just before this chapter runs
// (`register-execution-wallet.ts`), the same wallet that later signs every Settlement leg.
const bobsOwnWallet = wallet.generate();
const bobDestinationAddress = deriveTronAddress(bobsOwnWallet.wallet.accountExtendedPublicKey, 0);
await mercatto.executionDestinations.register(organizationId, bobAccountId, assetNetworkId, bobDestinationAddress);

const mercattoRevenueAllocation = await mercatto.wallets.allocateDepositAddress(applicationId, networkId);
await mercatto.executionDestinations.register(organizationId, mercattoRevenueAccountId, assetNetworkId, mercattoRevenueAllocation.address);

Result

Three real Accounts, each authorized for Mercatto's Application — a step that's easy to forget and fails loudly if skipped (see Failure scenarios) — and each with a registered ExecutionDestination, without which a real on-chain Settlement can't pay them at all (see Settlement and Split).

What happened under the hood

createAccountHolderInvitation doesn't create an Account by itself — the Account only exists once the invitation is claimed. Two different claim methods exist for a reason: signUpAndClaimInvitation is for someone who's never had an Ishtaran identity before (Bob and Alice here); a plain claimInvitation (no signup) is for someone who already has an AccountHolder session from a different marketplace, reusing the same underlying Account — the actual point of giving Bob his own login in the first place. Mercatto never sees either password.

Alternative covered separately: a one-off payer who never needs their own login gets an Organization-provisioned Account instead (accounts.create, no invitation) — see Failure scenarios.

A limit worth knowing now, not later: authorizeApplication requires Mercatto's Member session (owner), not its API Key — the API Key call is rejected. Same for everything under workflows.* in the next chapter. Once Bob and Alice have claimed their invitations, though, their own logins are done being useful for the rest of this story — every later financial call (balance, withdrawal) is Mercatto acting on their behalf with its own credentials, never their session directly. See Known Limitations for exactly why.

Registering an ExecutionDestination is not the same as having an Account. An Account can hold a balance without ever having a real on-chain receiving address on file — that's what ExecutionDestination is for (DEC-037): the address a Settlement's execution leg actually pays out to, first-registration-wins, never silently overwritten. It's deliberately not the same mechanism as WithdrawalDestination (no whitelist/cooldown) — this is a beneficiary declaring where they get paid as a marketplace seller, not an integrator-initiated withdrawal. Before this chapter runs, Mercatto also registers its own execution wallet (examples/marketplace-mercatto/register-execution-wallet.ts) — a wallet Mercatto generates and signs with entirely on its own machine (only the public extended key ever reaches Ishtaran); that wallet is what later signs every Settlement leg in Settlement and Split.