#Organization
GET /organization
Get the organization the request is authenticated against, including its plan and its resolved limits. The limits already have the plan's defaults resolved against anything set on the organization itself. Its behavior settings and time zone are on GET /settings.
Requires the settings:read permission.
curl \
"https://your-store.meisei.app/api/organization" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@meisei/api/admin/client"
import { getOrganization } from "@meisei/api/admin"
client.setConfig({
baseUrl: "https://your-store.meisei.app/api",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await getOrganization()require "meisei"
meisei = Meisei::Client.new(
secret_key: "sk_YOUR_SECRET_KEY",
base_url: "https://your-store.meisei.app/api",
)
result = meisei.organization.retrievefrom meisei import Client
meisei = Client(
secret_key="sk_YOUR_SECRET_KEY",
base_url="https://your-store.meisei.app/api",
)
result = meisei.organization.retrieve(){
"data": {
"id": "uHKNC81a",
"name": "string",
"slug": "string",
"logoUrl": "https://example.com",
"dashboardUrl": "https://example.com",
"customerPagesHost": "string",
"platformSender": "string",
"plan": "starter",
"limits": {
"sites": 0,
"products": 0,
"variantsPerProduct": 0,
"customers": 0,
"monthlySurveys": 0,
"monthlyEngagedUsers": 0,
"storedReviews": 0,
"monthlyEmails": 0,
"monthlyAiBudgetCents": 0,
"apiKeys": 0,
"seats": 0,
"pendingInvitations": 0,
"webhooks": 0,
"automations": 0,
"monthlyAutomationRuns": 0,
"automationRunCpuMs": 0,
"automationRunWallMs": 0,
"automationRunSubrequests": 0,
"automationRunApiCalls": 0,
"loyaltyPrograms": 0,
"currencies": 0,
"rulesPerLoyaltyProgram": 0,
"tiersPerLoyaltyProgram": 0,
"rewardsPerLoyaltyProgram": 0,
"savedCharts": 0,
"dashboards": 0,
"savedFilters": 0,
"quickFilters": 0,
"tagsPerResource": 0,
"wishlistsPerCustomer": 0,
"itemsPerWishlist": 0,
"brandAssetsMB": 0,
"totalStorageMB": 0,
"singleUploadMB": 0,
"assistantAttachmentBytes": 0,
"mediaPerReview": 0,
"monthlyReviewSubmissions": 0,
"webhookEventRetentionDays": 0,
"auditLogRetentionDays": 0,
"importJobRetentionDays": 0,
"importJobsPerDay": 0,
"exportJobsPerDay": 0,
"rowsPerImport": 0,
"rowsPerExport": 0,
"jobSliceRows": 0,
"jobAlarmBudgetMs": 0,
"heavyJobBatchesPerAlarm": 0,
"apiRequestsPerMinute": 0,
"mcpRequestsPerMinute": 0,
"loyaltyEventsPerMinute": 0,
"widgetRequestsPerSession": 0,
"emailsPerCustomerPerDay": 0,
"aiSummaryMinReviews": 0,
"aiSummaryRegenerateReviews": 0,
"aiSummaryRegeneratePercent": 0,
"aiSummaryMinHoursBetween": 0,
"monthlyReviewAnswers": 0,
"aiReviewSummaries": true,
"aiReviewAnswers": true,
"aiReviewScreening": true,
"aiReviewSentiment": true,
"sso": true,
"widgetEdgeCache": true
},
"access": {
"state": "active",
"writable": true,
"message": "string",
"trialEndsAt": "2025-01-15T09:30:00Z",
"readOnlySince": "2025-01-15T09:30:00Z",
"exportsUntil": "2025-01-15T09:30:00Z"
},
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
},
"role": "owner"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the organization.",
"idCodec": "controlPlane"
},
"name": {
"type": "string",
"description": "The organization's display name."
},
"slug": {
"type": "string",
"description": "The organization's unique handle. Your dashboard, your API and your storefront pages are all served from it. It can be changed once every 30 days, and the old handle keeps working afterwards."
},
"logoUrl": {
"anyOf": [
{
"type": "string",
"format": "uri"
},
{
"type": "null"
}
],
"description": "Public URL of the organization's logo image."
},
"dashboardUrl": {
"type": "string",
"format": "uri",
"description": "Where this organization's Meisei dashboard is served from, such as `https://halfmoon.meisei.app`. Its admin API answers under `/api` on the same origin."
},
"customerPagesHost": {
"type": "string",
"description": "The host Meisei serves the organization's customer pages on, such as `halfmoon.meisei.app`. A site's own hostname replaces it once its certificate is issued."
},
"platformSender": {
"type": "string",
"description": "The address Meisei sends a site's shopper emails from until the site has a verified sending domain and an address of its own, such as `halfmoon-reviews@meisei.app`."
},
"plan": {
"type": "string",
"enum": ["starter", "growth", "scale", "unlimited"],
"description": "The plan the organization has committed to, which is the least it is billed each month and the set of default limits it is held to. Each month is billed at the cheapest plan at or above it that covers the customers the store actually had. Any individual limit can still be overridden on the organization."
},
"limits": {
"type": "object",
"properties": {
"sites": {
"type": "number",
"description": "How many sites the organization may connect."
},
"products": {
"type": "number",
"description": "How many products the organization may store."
},
"variantsPerProduct": {
"type": "number",
"description": "How many variants a single product may have."
},
"customers": {
"type": "number",
"description": "How many customers the organization may store."
},
"monthlySurveys": {
"type": "number",
"description": "How many surveys may be sent per calendar month."
},
"monthlyEngagedUsers": {
"type": "number",
"description": "How many engaged customers the plan includes in a calendar month. A customer counts once a month if they order, earn or spend points, or use a wishlist."
},
"storedReviews": {
"type": "number",
"description": "How many reviews the organization may store."
},
"monthlyEmails": {
"type": "number",
"description": "How many emails the organization may send to its customers in a calendar month. During a trial, it is the total for the whole trial."
},
"monthlyAiBudgetCents": {
"type": "number",
"description": "How much AI model spend the organization's AI features may use in a calendar month, in US cents. During a trial, it is the total for the whole trial."
},
"apiKeys": {
"type": "number",
"description": "How many API keys the organization may hold at once."
},
"seats": {
"type": "number",
"description": "How many people may be members of the organization."
},
"pendingInvitations": {
"type": "number",
"description": "How many invitations may be waiting to be accepted at once."
},
"webhooks": {
"type": "number",
"description": "How many webhook endpoints the organization may register."
},
"automations": {
"type": "number",
"description": "How many automations the organization may keep."
},
"monthlyAutomationRuns": {
"type": "number",
"description": "How many automation runs events and schedules may start in a calendar month. Past it, runs are skipped until the month resets."
},
"automationRunCpuMs": {
"type": "number",
"description": "How many milliseconds of processing time one automation run may use. Waiting on the API or another service does not count."
},
"automationRunWallMs": {
"type": "number",
"description": "How many milliseconds one automation run may take in total, waiting included."
},
"automationRunSubrequests": {
"type": "number",
"description": "How many requests to other services one automation run may make. Calls to the Meisei API are not among them."
},
"automationRunApiCalls": {
"type": "number",
"description": "How many Meisei API calls one automation run may make."
},
"loyaltyPrograms": {
"type": "number",
"description": "How many loyalty programs the organization may run."
},
"currencies": {
"type": "number",
"description": "How many currencies the organization may trade in."
},
"rulesPerLoyaltyProgram": {
"type": "number",
"description": "How many earning rules a single loyalty program may have."
},
"tiersPerLoyaltyProgram": {
"type": "number",
"description": "How many tiers a single loyalty program may have."
},
"rewardsPerLoyaltyProgram": {
"type": "number",
"description": "How many reward definitions a single loyalty program may offer."
},
"savedCharts": {
"type": "number",
"description": "How many saved charts the organization may keep."
},
"dashboards": {
"type": "number",
"description": "How many dashboards the organization may keep."
},
"savedFilters": {
"type": "number",
"description": "How many saved filters the organization may keep."
},
"quickFilters": {
"type": "number",
"description": "How many quick filters the organization may pin."
},
"tagsPerResource": {
"type": "number",
"description": "How many tags may be attached to a single customer, product, or order."
},
"wishlistsPerCustomer": {
"type": "number",
"description": "How many wishlists a single customer may have."
},
"itemsPerWishlist": {
"type": "number",
"description": "How many items a single wishlist may hold."
},
"brandAssetsMB": {
"type": "number",
"description": "How many megabytes of brand assets each site may hold."
},
"totalStorageMB": {
"type": "number",
"description": "How many megabytes of uploaded files the organization may hold in total."
},
"singleUploadMB": {
"type": "number",
"description": "How many megabytes a single uploaded file may be."
},
"assistantAttachmentBytes": {
"type": "number",
"description": "How many bytes of attachments a single message to the assistant may carry."
},
"mediaPerReview": {
"type": "number",
"description": "How many photos or videos a single review may carry."
},
"monthlyReviewSubmissions": {
"type": "number",
"description": "How many reviews may be submitted per calendar month."
},
"webhookEventRetentionDays": {
"type": "number",
"description": "How many days of webhook delivery history are kept before being purged."
},
"auditLogRetentionDays": {
"type": "number",
"description": "How many days of audit log entries are kept before being purged."
},
"importJobRetentionDays": {
"type": "number",
"description": "How many days an import job is kept, along with the source file and the links to the records it wrote, before being purged."
},
"importJobsPerDay": {
"type": "number",
"description": "How many import jobs may be started per day."
},
"exportJobsPerDay": {
"type": "number",
"description": "How many export jobs may be started per day."
},
"rowsPerImport": {
"type": "number",
"description": "How many rows a single import may carry."
},
"rowsPerExport": {
"type": "number",
"description": "How many rows a single export may produce."
},
"jobSliceRows": {
"type": "number",
"description": "How many rows one slice of a long background job (an import, an export, a backfill) handles before it lets other work run."
},
"jobAlarmBudgetMs": {
"type": "number",
"description": "How many milliseconds the organization's background queue runs at a time before it lets requests in."
},
"heavyJobBatchesPerAlarm": {
"type": "number",
"description": "How many batches of the heavy background queues (imports, exports, backfills, purges) run each time the queue wakes. 0 pauses them."
},
"apiRequestsPerMinute": {
"type": "number",
"description": "How many admin API requests every secret key in the organization shares per minute."
},
"mcpRequestsPerMinute": {
"type": "number",
"description": "How many MCP requests every OAuth connection to the organization shares per minute."
},
"loyaltyEventsPerMinute": {
"type": "number",
"description": "How many events `POST /loyalty-events` accepts per minute."
},
"widgetRequestsPerSession": {
"type": "number",
"description": "How many widget API requests one shopper session may make."
},
"emailsPerCustomerPerDay": {
"type": "number",
"description": "How many emails a single customer may be sent in a day."
},
"aiSummaryMinReviews": {
"type": "number",
"description": "How many published reviews a product needs before a summary is generated or shown."
},
"aiSummaryRegenerateReviews": {
"type": "number",
"description": "How far the published review count has to move from the stored summary's count before it is regenerated."
},
"aiSummaryRegeneratePercent": {
"type": "number",
"description": "How far the published review count has to move, as a percentage of the stored summary's count, before it is regenerated. Either this or `aiSummaryRegenerateReviews` triggers it."
},
"aiSummaryMinHoursBetween": {
"type": "number",
"description": "The shortest gap between two generated summaries for one product. The default of 24 is the one regeneration per product per day ceiling."
},
"monthlyReviewAnswers": {
"type": "number",
"description": "How many review answers may be generated per calendar month. Repeated questions are answered from cache and do not count."
},
"aiReviewSummaries": {
"type": "boolean",
"description": "Whether the organization can generate AI summaries of a product's reviews."
},
"aiReviewAnswers": {
"type": "boolean",
"description": "Whether shoppers can ask a question on a product page and get an answer generated from its published reviews."
},
"aiReviewScreening": {
"type": "boolean",
"description": "Whether arriving reviews are screened by the AI moderation model."
},
"aiReviewSentiment": {
"type": "boolean",
"description": "Whether arriving reviews are labeled positive, neutral or negative by a model reading their text."
},
"sso": {
"type": "boolean",
"description": "Whether the organization can sign in through its own SSO provider."
},
"widgetEdgeCache": {
"type": "boolean",
"description": "Whether storefront widget reads that are the same for every shopper are cached for a short time at the edge."
}
},
"required": [
"sites",
"products",
"variantsPerProduct",
"customers",
"monthlySurveys",
"monthlyEngagedUsers",
"storedReviews",
"monthlyEmails",
"monthlyAiBudgetCents",
"apiKeys",
"seats",
"pendingInvitations",
"webhooks",
"automations",
"monthlyAutomationRuns",
"automationRunCpuMs",
"automationRunWallMs",
"automationRunSubrequests",
"automationRunApiCalls",
"loyaltyPrograms",
"currencies",
"rulesPerLoyaltyProgram",
"tiersPerLoyaltyProgram",
"rewardsPerLoyaltyProgram",
"savedCharts",
"dashboards",
"savedFilters",
"quickFilters",
"tagsPerResource",
"wishlistsPerCustomer",
"itemsPerWishlist",
"brandAssetsMB",
"totalStorageMB",
"singleUploadMB",
"assistantAttachmentBytes",
"mediaPerReview",
"monthlyReviewSubmissions",
"webhookEventRetentionDays",
"auditLogRetentionDays",
"importJobRetentionDays",
"importJobsPerDay",
"exportJobsPerDay",
"rowsPerImport",
"rowsPerExport",
"jobSliceRows",
"jobAlarmBudgetMs",
"heavyJobBatchesPerAlarm",
"apiRequestsPerMinute",
"mcpRequestsPerMinute",
"loyaltyEventsPerMinute",
"widgetRequestsPerSession",
"emailsPerCustomerPerDay",
"aiSummaryMinReviews",
"aiSummaryRegenerateReviews",
"aiSummaryRegeneratePercent",
"aiSummaryMinHoursBetween",
"monthlyReviewAnswers",
"aiReviewSummaries",
"aiReviewAnswers",
"aiReviewScreening",
"aiReviewSentiment",
"sso",
"widgetEdgeCache"
],
"additionalProperties": false,
"description": "The limits this organization is held to, with the plan's defaults already resolved against anything set on the organization itself."
},
"access": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": ["active", "trialing", "trial-ended", "canceled"],
"description": "Where the organization stands with its plan: `active` when something is paying, `trialing` during the free trial, and `trial-ended` or `canceled` once nothing is."
},
"writable": {
"type": "boolean",
"description": "Whether the organization can be changed. When it is false every create, update and delete is refused with a 402, and reads and exports keep working."
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Why writes are refused, as a sentence to show the merchant. It is the same wording the API refuses with. Null while the organization is writable."
},
"trialEndsAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the free trial ends, while one is running. Null otherwise."
},
"readOnlySince": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the organization became read-only. Null while it is writable."
},
"exportsUntil": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "The end of the export window a read-only organization is given. Nothing is deleted on that date, and exports carry on working."
}
},
"required": [
"state",
"writable",
"message",
"trialEndsAt",
"readOnlySince",
"exportsUntil"
],
"additionalProperties": false,
"description": "Whether this organization can be changed, and what to do if not."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the organization was created."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the organization was last changed."
}
},
"required": [
"id",
"name",
"slug",
"logoUrl",
"dashboardUrl",
"customerPagesHost",
"platformSender",
"plan",
"limits",
"access",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The current organization."
},
"role": {
"anyOf": [
{
"type": "string",
"enum": ["owner", "member"],
"description": "What a person may do in the organization. An owner can also manage who is in the organization and what each person may do. A member can use everything else."
},
{
"type": "null"
}
],
"description": "Your role in this organization. Null when the request is authenticated with an API key or an OAuth connection, since those act for the whole organization rather than for a person."
}
},
"required": ["data", "role"],
"additionalProperties": false
}PATCH /organization
Update the current organization's profile: its display name, its logo or its handle. Only the fields you send are changed; the rest are left alone. All three are recorded in the audit trail. Changing the handle moves the organization's host, so it is allowed once every 30 days and the old handle keeps resolving afterwards. Behavior settings and the time zone are on PATCH /settings.
Requires the settings:write permission.
Body parameters
namestringA new display name for the organization.
logostring | nullThe key of an image uploaded through POST /organization/logo/upload-url, or null to remove the logo.
slugstringA new handle for the organization: lowercase letters, numbers and hyphens, 3 to 63 characters. The old handle is kept and keeps resolving, so existing links, embed snippets and configured base URLs go on working. Refused if the handle is reserved, already taken, or if the handle changed in the last 30 days.
curl \
-X PATCH \
"https://your-store.meisei.app/api/organization" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"logo": "string",
"slug": "string"
}'import { client } from "@meisei/api/admin/client"
import { patchOrganization } from "@meisei/api/admin"
client.setConfig({
baseUrl: "https://your-store.meisei.app/api",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await patchOrganization({
body: {
name: "string",
logo: "string",
slug: "string",
},
})require "meisei"
meisei = Meisei::Client.new(
secret_key: "sk_YOUR_SECRET_KEY",
base_url: "https://your-store.meisei.app/api",
)
result = meisei.organization.update(
name: "string",
logo: "string",
slug: "string",
)from meisei import Client
meisei = Client(
secret_key="sk_YOUR_SECRET_KEY",
base_url="https://your-store.meisei.app/api",
)
result = meisei.organization.update(name="string", logo="string", slug="string"){
"id": "uHKNC81a",
"name": "string",
"slug": "string",
"logoUrl": "https://example.com",
"dashboardUrl": "https://example.com",
"customerPagesHost": "string",
"platformSender": "string",
"plan": "starter",
"limits": {
"sites": 0,
"products": 0,
"variantsPerProduct": 0,
"customers": 0,
"monthlySurveys": 0,
"monthlyEngagedUsers": 0,
"storedReviews": 0,
"monthlyEmails": 0,
"monthlyAiBudgetCents": 0,
"apiKeys": 0,
"seats": 0,
"pendingInvitations": 0,
"webhooks": 0,
"automations": 0,
"monthlyAutomationRuns": 0,
"automationRunCpuMs": 0,
"automationRunWallMs": 0,
"automationRunSubrequests": 0,
"automationRunApiCalls": 0,
"loyaltyPrograms": 0,
"currencies": 0,
"rulesPerLoyaltyProgram": 0,
"tiersPerLoyaltyProgram": 0,
"rewardsPerLoyaltyProgram": 0,
"savedCharts": 0,
"dashboards": 0,
"savedFilters": 0,
"quickFilters": 0,
"tagsPerResource": 0,
"wishlistsPerCustomer": 0,
"itemsPerWishlist": 0,
"brandAssetsMB": 0,
"totalStorageMB": 0,
"singleUploadMB": 0,
"assistantAttachmentBytes": 0,
"mediaPerReview": 0,
"monthlyReviewSubmissions": 0,
"webhookEventRetentionDays": 0,
"auditLogRetentionDays": 0,
"importJobRetentionDays": 0,
"importJobsPerDay": 0,
"exportJobsPerDay": 0,
"rowsPerImport": 0,
"rowsPerExport": 0,
"jobSliceRows": 0,
"jobAlarmBudgetMs": 0,
"heavyJobBatchesPerAlarm": 0,
"apiRequestsPerMinute": 0,
"mcpRequestsPerMinute": 0,
"loyaltyEventsPerMinute": 0,
"widgetRequestsPerSession": 0,
"emailsPerCustomerPerDay": 0,
"aiSummaryMinReviews": 0,
"aiSummaryRegenerateReviews": 0,
"aiSummaryRegeneratePercent": 0,
"aiSummaryMinHoursBetween": 0,
"monthlyReviewAnswers": 0,
"aiReviewSummaries": true,
"aiReviewAnswers": true,
"aiReviewScreening": true,
"aiReviewSentiment": true,
"sso": true,
"widgetEdgeCache": true
},
"access": {
"state": "active",
"writable": true,
"message": "string",
"trialEndsAt": "2025-01-15T09:30:00Z",
"readOnlySince": "2025-01-15T09:30:00Z",
"exportsUntil": "2025-01-15T09:30:00Z"
},
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the organization.",
"idCodec": "controlPlane"
},
"name": {
"type": "string",
"description": "The organization's display name."
},
"slug": {
"type": "string",
"description": "The organization's unique handle. Your dashboard, your API and your storefront pages are all served from it. It can be changed once every 30 days, and the old handle keeps working afterwards."
},
"logoUrl": {
"anyOf": [
{
"type": "string",
"format": "uri"
},
{
"type": "null"
}
],
"description": "Public URL of the organization's logo image."
},
"dashboardUrl": {
"type": "string",
"format": "uri",
"description": "Where this organization's Meisei dashboard is served from, such as `https://halfmoon.meisei.app`. Its admin API answers under `/api` on the same origin."
},
"customerPagesHost": {
"type": "string",
"description": "The host Meisei serves the organization's customer pages on, such as `halfmoon.meisei.app`. A site's own hostname replaces it once its certificate is issued."
},
"platformSender": {
"type": "string",
"description": "The address Meisei sends a site's shopper emails from until the site has a verified sending domain and an address of its own, such as `halfmoon-reviews@meisei.app`."
},
"plan": {
"type": "string",
"enum": ["starter", "growth", "scale", "unlimited"],
"description": "The plan the organization has committed to, which is the least it is billed each month and the set of default limits it is held to. Each month is billed at the cheapest plan at or above it that covers the customers the store actually had. Any individual limit can still be overridden on the organization."
},
"limits": {
"type": "object",
"properties": {
"sites": {
"type": "number",
"description": "How many sites the organization may connect."
},
"products": {
"type": "number",
"description": "How many products the organization may store."
},
"variantsPerProduct": {
"type": "number",
"description": "How many variants a single product may have."
},
"customers": {
"type": "number",
"description": "How many customers the organization may store."
},
"monthlySurveys": {
"type": "number",
"description": "How many surveys may be sent per calendar month."
},
"monthlyEngagedUsers": {
"type": "number",
"description": "How many engaged customers the plan includes in a calendar month. A customer counts once a month if they order, earn or spend points, or use a wishlist."
},
"storedReviews": {
"type": "number",
"description": "How many reviews the organization may store."
},
"monthlyEmails": {
"type": "number",
"description": "How many emails the organization may send to its customers in a calendar month. During a trial, it is the total for the whole trial."
},
"monthlyAiBudgetCents": {
"type": "number",
"description": "How much AI model spend the organization's AI features may use in a calendar month, in US cents. During a trial, it is the total for the whole trial."
},
"apiKeys": {
"type": "number",
"description": "How many API keys the organization may hold at once."
},
"seats": {
"type": "number",
"description": "How many people may be members of the organization."
},
"pendingInvitations": {
"type": "number",
"description": "How many invitations may be waiting to be accepted at once."
},
"webhooks": {
"type": "number",
"description": "How many webhook endpoints the organization may register."
},
"automations": {
"type": "number",
"description": "How many automations the organization may keep."
},
"monthlyAutomationRuns": {
"type": "number",
"description": "How many automation runs events and schedules may start in a calendar month. Past it, runs are skipped until the month resets."
},
"automationRunCpuMs": {
"type": "number",
"description": "How many milliseconds of processing time one automation run may use. Waiting on the API or another service does not count."
},
"automationRunWallMs": {
"type": "number",
"description": "How many milliseconds one automation run may take in total, waiting included."
},
"automationRunSubrequests": {
"type": "number",
"description": "How many requests to other services one automation run may make. Calls to the Meisei API are not among them."
},
"automationRunApiCalls": {
"type": "number",
"description": "How many Meisei API calls one automation run may make."
},
"loyaltyPrograms": {
"type": "number",
"description": "How many loyalty programs the organization may run."
},
"currencies": {
"type": "number",
"description": "How many currencies the organization may trade in."
},
"rulesPerLoyaltyProgram": {
"type": "number",
"description": "How many earning rules a single loyalty program may have."
},
"tiersPerLoyaltyProgram": {
"type": "number",
"description": "How many tiers a single loyalty program may have."
},
"rewardsPerLoyaltyProgram": {
"type": "number",
"description": "How many reward definitions a single loyalty program may offer."
},
"savedCharts": {
"type": "number",
"description": "How many saved charts the organization may keep."
},
"dashboards": {
"type": "number",
"description": "How many dashboards the organization may keep."
},
"savedFilters": {
"type": "number",
"description": "How many saved filters the organization may keep."
},
"quickFilters": {
"type": "number",
"description": "How many quick filters the organization may pin."
},
"tagsPerResource": {
"type": "number",
"description": "How many tags may be attached to a single customer, product, or order."
},
"wishlistsPerCustomer": {
"type": "number",
"description": "How many wishlists a single customer may have."
},
"itemsPerWishlist": {
"type": "number",
"description": "How many items a single wishlist may hold."
},
"brandAssetsMB": {
"type": "number",
"description": "How many megabytes of brand assets each site may hold."
},
"totalStorageMB": {
"type": "number",
"description": "How many megabytes of uploaded files the organization may hold in total."
},
"singleUploadMB": {
"type": "number",
"description": "How many megabytes a single uploaded file may be."
},
"assistantAttachmentBytes": {
"type": "number",
"description": "How many bytes of attachments a single message to the assistant may carry."
},
"mediaPerReview": {
"type": "number",
"description": "How many photos or videos a single review may carry."
},
"monthlyReviewSubmissions": {
"type": "number",
"description": "How many reviews may be submitted per calendar month."
},
"webhookEventRetentionDays": {
"type": "number",
"description": "How many days of webhook delivery history are kept before being purged."
},
"auditLogRetentionDays": {
"type": "number",
"description": "How many days of audit log entries are kept before being purged."
},
"importJobRetentionDays": {
"type": "number",
"description": "How many days an import job is kept, along with the source file and the links to the records it wrote, before being purged."
},
"importJobsPerDay": {
"type": "number",
"description": "How many import jobs may be started per day."
},
"exportJobsPerDay": {
"type": "number",
"description": "How many export jobs may be started per day."
},
"rowsPerImport": {
"type": "number",
"description": "How many rows a single import may carry."
},
"rowsPerExport": {
"type": "number",
"description": "How many rows a single export may produce."
},
"jobSliceRows": {
"type": "number",
"description": "How many rows one slice of a long background job (an import, an export, a backfill) handles before it lets other work run."
},
"jobAlarmBudgetMs": {
"type": "number",
"description": "How many milliseconds the organization's background queue runs at a time before it lets requests in."
},
"heavyJobBatchesPerAlarm": {
"type": "number",
"description": "How many batches of the heavy background queues (imports, exports, backfills, purges) run each time the queue wakes. 0 pauses them."
},
"apiRequestsPerMinute": {
"type": "number",
"description": "How many admin API requests every secret key in the organization shares per minute."
},
"mcpRequestsPerMinute": {
"type": "number",
"description": "How many MCP requests every OAuth connection to the organization shares per minute."
},
"loyaltyEventsPerMinute": {
"type": "number",
"description": "How many events `POST /loyalty-events` accepts per minute."
},
"widgetRequestsPerSession": {
"type": "number",
"description": "How many widget API requests one shopper session may make."
},
"emailsPerCustomerPerDay": {
"type": "number",
"description": "How many emails a single customer may be sent in a day."
},
"aiSummaryMinReviews": {
"type": "number",
"description": "How many published reviews a product needs before a summary is generated or shown."
},
"aiSummaryRegenerateReviews": {
"type": "number",
"description": "How far the published review count has to move from the stored summary's count before it is regenerated."
},
"aiSummaryRegeneratePercent": {
"type": "number",
"description": "How far the published review count has to move, as a percentage of the stored summary's count, before it is regenerated. Either this or `aiSummaryRegenerateReviews` triggers it."
},
"aiSummaryMinHoursBetween": {
"type": "number",
"description": "The shortest gap between two generated summaries for one product. The default of 24 is the one regeneration per product per day ceiling."
},
"monthlyReviewAnswers": {
"type": "number",
"description": "How many review answers may be generated per calendar month. Repeated questions are answered from cache and do not count."
},
"aiReviewSummaries": {
"type": "boolean",
"description": "Whether the organization can generate AI summaries of a product's reviews."
},
"aiReviewAnswers": {
"type": "boolean",
"description": "Whether shoppers can ask a question on a product page and get an answer generated from its published reviews."
},
"aiReviewScreening": {
"type": "boolean",
"description": "Whether arriving reviews are screened by the AI moderation model."
},
"aiReviewSentiment": {
"type": "boolean",
"description": "Whether arriving reviews are labeled positive, neutral or negative by a model reading their text."
},
"sso": {
"type": "boolean",
"description": "Whether the organization can sign in through its own SSO provider."
},
"widgetEdgeCache": {
"type": "boolean",
"description": "Whether storefront widget reads that are the same for every shopper are cached for a short time at the edge."
}
},
"required": [
"sites",
"products",
"variantsPerProduct",
"customers",
"monthlySurveys",
"monthlyEngagedUsers",
"storedReviews",
"monthlyEmails",
"monthlyAiBudgetCents",
"apiKeys",
"seats",
"pendingInvitations",
"webhooks",
"automations",
"monthlyAutomationRuns",
"automationRunCpuMs",
"automationRunWallMs",
"automationRunSubrequests",
"automationRunApiCalls",
"loyaltyPrograms",
"currencies",
"rulesPerLoyaltyProgram",
"tiersPerLoyaltyProgram",
"rewardsPerLoyaltyProgram",
"savedCharts",
"dashboards",
"savedFilters",
"quickFilters",
"tagsPerResource",
"wishlistsPerCustomer",
"itemsPerWishlist",
"brandAssetsMB",
"totalStorageMB",
"singleUploadMB",
"assistantAttachmentBytes",
"mediaPerReview",
"monthlyReviewSubmissions",
"webhookEventRetentionDays",
"auditLogRetentionDays",
"importJobRetentionDays",
"importJobsPerDay",
"exportJobsPerDay",
"rowsPerImport",
"rowsPerExport",
"jobSliceRows",
"jobAlarmBudgetMs",
"heavyJobBatchesPerAlarm",
"apiRequestsPerMinute",
"mcpRequestsPerMinute",
"loyaltyEventsPerMinute",
"widgetRequestsPerSession",
"emailsPerCustomerPerDay",
"aiSummaryMinReviews",
"aiSummaryRegenerateReviews",
"aiSummaryRegeneratePercent",
"aiSummaryMinHoursBetween",
"monthlyReviewAnswers",
"aiReviewSummaries",
"aiReviewAnswers",
"aiReviewScreening",
"aiReviewSentiment",
"sso",
"widgetEdgeCache"
],
"additionalProperties": false,
"description": "The limits this organization is held to, with the plan's defaults already resolved against anything set on the organization itself."
},
"access": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": ["active", "trialing", "trial-ended", "canceled"],
"description": "Where the organization stands with its plan: `active` when something is paying, `trialing` during the free trial, and `trial-ended` or `canceled` once nothing is."
},
"writable": {
"type": "boolean",
"description": "Whether the organization can be changed. When it is false every create, update and delete is refused with a 402, and reads and exports keep working."
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Why writes are refused, as a sentence to show the merchant. It is the same wording the API refuses with. Null while the organization is writable."
},
"trialEndsAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the free trial ends, while one is running. Null otherwise."
},
"readOnlySince": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the organization became read-only. Null while it is writable."
},
"exportsUntil": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "The end of the export window a read-only organization is given. Nothing is deleted on that date, and exports carry on working."
}
},
"required": ["state", "writable", "message", "trialEndsAt", "readOnlySince", "exportsUntil"],
"additionalProperties": false,
"description": "Whether this organization can be changed, and what to do if not."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the organization was created."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the organization was last changed."
}
},
"required": [
"id",
"name",
"slug",
"logoUrl",
"dashboardUrl",
"customerPagesHost",
"platformSender",
"plan",
"limits",
"access",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The updated organization."
}POST /organization/logo/upload-url
Get a short-lived URL to upload an organization logo to. PUT the image's bytes to uploadUrl, then send the returned key as logo on PATCH /organization. The image is served from a public URL and can be at most 2 MB.
Requires the settings:write permission.
Body parameters
fileNamestringrequiredThe file's name, including its extension.
sizeBytesintegerSize of the file in bytes, if you know it up front.
contentTypeimage/png | image/jpeg | image/gif | image/webp | image/avifThe image's MIME type: PNG, JPEG, GIF, WebP or AVIF. The upload is stored and served as this type, whatever the upload request says. Leave it out and the upload's own type is used, but only an image of one of these types can be set as a logo or avatar.
curl \
-X POST \
"https://your-store.meisei.app/api/organization/logo/upload-url" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"fileName": "string",
"sizeBytes": 0,
"contentType": "image/png"
}'import { client } from "@meisei/api/admin/client"
import { postOrganizationLogoUploadUrl } from "@meisei/api/admin"
client.setConfig({
baseUrl: "https://your-store.meisei.app/api",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await postOrganizationLogoUploadUrl({
body: {
fileName: "string",
sizeBytes: 0,
contentType: "image/png",
},
})require "meisei"
meisei = Meisei::Client.new(
secret_key: "sk_YOUR_SECRET_KEY",
base_url: "https://your-store.meisei.app/api",
)
result = meisei.organization.logo.upload_url(
file_name: "string",
size_bytes: 0,
content_type: "image/png",
)from meisei import Client
meisei = Client(
secret_key="sk_YOUR_SECRET_KEY",
base_url="https://your-store.meisei.app/api",
)
result = meisei.organization.logo.upload_url(
file_name="string",
size_bytes=0,
content_type="image/png",
){
"key": "string",
"uploadUrl": "https://example.com",
"expiresAt": "2025-01-15T09:30:00Z"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "The storage key for the image. Pass this to the endpoint that consumes it."
},
"uploadUrl": {
"type": "string",
"format": "uri",
"description": "PUT the image's bytes to this URL before the expiry."
},
"expiresAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the upload URL stops working."
}
},
"required": ["key", "uploadUrl", "expiresAt"],
"additionalProperties": false
}