Skip to content

Clients

A solutions partner manages other organizations, its clients. A partner can list its clients and read how well each one is using Mereon with read, and create a new client with client:create.

Every endpoint on this page answers for the organization the connection is pinned to, and refuses one that is not a solutions partner with 403 (NOT_MSP_ORGANIZATION).

GET /v1/clients

The partner’s active clients, by name. Archived clients are left out. Needs the access an organization admin has: owners, admins and billing admins. Anyone else gets 403.

Parameter Type Notes
cursor string nextCursor from the previous page.
limit integer 1 to 100, default 50.
Terminal window
curl "https://api.mereon.ai/v1/clients" \
-H "Authorization: Bearer $MEREON_TOKEN"
{
"data": [
{
"id": "org_7f2a...",
"name": "Acme Plumbing",
"domain": "acmeplumbing.com",
"billing": "reseller",
"paidBy": "partner",
"referralCommission": null,
"resellerDiscount": 0.2,
"memberCount": 14,
"subscription": {
"product": "Pro",
"status": "trialing",
"trialEndsAt": "2026-11-22T15:04:05.000Z"
},
"createdAt": "2026-10-23T15:04:05.000Z",
"url": "https://mereon.ai/solutions-partner/clients"
}
],
"nextCursor": null
}

billing is reseller (the partner pays for the client) or referral (the client pays for itself and the partner earns a commission). It is null for an old client created before it was recorded. referralCommission and resellerDiscount are fractions, so 0.2 is 20%, and only the one that applies to the client’s billing is set. subscription.status is Stripe’s status (trialing, active, past_due and so on), or comped for a free plan set up by support.

GET /v1/clients/{id}/adoption

How well one client is using Mereon. Every figure is a count: no person is named. A client that is not one of this partner’s active clients is refused with 404. Needs the same access as listing clients.

{
"healthTier": "getting-started",
"windowDays": 7,
"activity": { "current": 42, "previous": 30, "percentChange": 40 },
"questionsAsked": { "current": 9, "previous": 0, "percentChange": null },
"lessonsCompleted": { "current": 5, "previous": 6, "percentChange": -17 },
"activeMembers7d": 6,
"activeMembers30d": 11,
"totalMembers": 14,
"seatsLicensed": 15,
"contentCount": 23,
"outstandingObligations": 8
}

healthTier is dormant when nobody has signed in recently, getting-started when people sign in but the client has no content or little activity, and active otherwise. Each change compares the last windowDays days with the same length of time before them. percentChange is null when there is nothing to compare with.

GET /v1/clients/terms

What creating a client with this billing would mean for this partner, before anything is created: who pays, the commission or discount copied onto the client, and the Pro trial it starts on. summary says it in a sentence to show the person before they agree.

It runs the checks Create a client runs, so a referral partner who takes a commission and has not finished Stripe payout setup is refused with 400 (REFERRAL_PAYOUT_REQUIRED), and a reseller partner with no default payment method with 400 (MSP_PAYMENT_METHOD_REQUIRED). Needs client:create. Limited to 10 calls a minute and 60 an hour.

Parameter Type Required Notes
billing reseller | referral yes How the client would be billed.
{
"billing": "reseller",
"paidBy": "partner",
"referralCommission": null,
"resellerDiscount": 0.2,
"trialDays": 30,
"summary": "Northwind Partners pays for the client's subscription, discounted by 20%. The client starts on a 30-day Pro trial, which is billed to Northwind Partners when it ends."
}

POST /v1/clients

Creates a client of the partner, as the new-client page in Mereon does: the organization, a Pro trial (billed to the partner for a reseller client), and an invitation to its owner when one is named. The owner becomes the client’s owner when they accept. You are not moved into the client in the app.

Needs client:create, which owners, admins and billing admins can grant. Limited to 5 calls a minute and 30 an hour, counting retries.

Field Type Required Notes
name string yes One line, up to 200 characters.
domain string no The client’s website or domain. A value that is not one is refused with 400.
billing reseller | referral yes reseller: the partner pays, at its reseller discount. referral: the client pays, and the partner earns its referral commission.
owner object no { "name", "email" }. Who owns the client. Leave it out and nobody is invited.
requestKey string yes A key you choose, 8 to 100 letters, digits, ., _, : or -. Send the same one when you retry this request, and a new one for the next client.

requestKey makes the call safe to retry after a timeout or an error. A call with a key that already created a client answers 200 with that client and created: false: nothing new is created and nobody is billed again. If the first call stopped before the trial started, or before the owner was invited, the retry finishes it, and sends no second email to an owner who was already invited. A trial that was started is never started again, even after it ends.

A retry that arrives while an earlier call with the same key is still setting the client up is refused with 409 (CLIENT_REQUEST_IN_PROGRESS) and changes nothing; send the same request again in a minute. The same key with a different request (another name, domain, billing or owner) is refused with 409 (CLIENT_REQUEST_KEY_REUSED), and so is a key whose client has since been archived.

A retry can come at any time. One that arrives days later still finds a trial the first call started, so it is not charged twice.

Terminal window
curl -X POST "https://api.mereon.ai/v1/clients" \
-H "Authorization: Bearer $MEREON_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Plumbing",
"domain": "acmeplumbing.com",
"billing": "reseller",
"owner": { "name": "Sam Rivera", "email": "sam@acmeplumbing.com" },
"requestKey": "acme-plumbing-2026-10"
}'

201 Created, or 200 for a retry.

{
"client": {
"id": "org_7f2a...",
"name": "Acme Plumbing",
"domain": "acmeplumbing.com",
"billing": "reseller",
"paidBy": "partner",
"referralCommission": null,
"resellerDiscount": 0.2,
"memberCount": 0,
"subscription": { "product": "Pro", "status": "trialing", "trialEndsAt": "2026-11-22T15:04:05.000Z" },
"createdAt": "2026-10-23T15:04:05.000Z",
"url": "https://mereon.ai/solutions-partner/clients"
},
"created": true,
"terms": {
"billing": "reseller",
"paidBy": "partner",
"referralCommission": null,
"resellerDiscount": 0.2,
"trialDays": 30,
"summary": "Northwind Partners pays for the client's subscription, discounted by 20%. The client starts on a 30-day Pro trial, which is billed to Northwind Partners when it ends."
},
"owner": { "status": "invited", "email": "sam@acmeplumbing.com", "message": null },
"connect": {
"organizationId": "org_7f2a...",
"instructions": "This connection stays with Northwind Partners, so it cannot act in Acme Plumbing. To set up Acme Plumbing, connect again and choose Acme Plumbing on the consent screen..."
}
}

owner.status is one of:

Status Meaning
invited The invitation was sent now.
pending An invitation sent earlier still stands and will make them the owner.
accepted The client already has an owner.
not-requested No owner was named, so nobody was invited.
failed The client exists and nobody was invited. message says why. Retrying with the same requestKey tries the invitation again.

A failed invitation does not fail the request: the client was created, and the response says so.

The creation is recorded in the partner’s audit log and in the new client’s own, so the client’s admins can see who created it and how it is billed.