2 operations. Every schema and example on this page is generated from the platform contract.
Runs the deterministic G02 icon pipeline over the merchant's logo (or an image they uploaded into their own app-icons folder) and stores the result as the canonical 1024x1024 PNG with no alpha channel, the two things Apple hard-rejects an icon for. Refuses with a specific, actionable message when the source is an SVG, is under 512px on its shortest side, or is over 10MB, so the merchant learns at intake rather than at App Store Connect upload weeks later. Never crops: a non-square logo is padded onto the store's brand colour.
Store the icon belongs to (also authorises the merchant).
Storage path of an already-uploaded image under the store's own app-icons folder. Omit to generate from the store logo.
Proceed despite a low-contrast warning, the merchant has seen it and chosen to keep the icon.
Canonical object path, the only icon the build lane reads.
Short-lived URL for the merchant confirm step and the operator console.
Colour transparency was flattened onto, as #RRGGBB.
True when the upload really carried transparency and we removed it.
True when a non-square source was padded. Never cropped.
Digest of the exact canonical bytes, for tying a build to an icon.
Every asset-catalogue size derived from the canonical icon.
Merchant-readable. A warning only, it never blocks the icon.
curl -X POST "https://www.membber.com/api/v1/own-app/icon" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/own-app/icon", {
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.generateOwnAppIcon(
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066"
))
).ok.body.json
print(response){
"app_icon_ref": "<app_icon_ref>",
"preview_url": "https://example.com/image.jpg",
"background": "<background>",
"flattened_alpha": true,
"padded": true,
"sha256": "<sha256>",
"source": {
"width": 1,
"height": 1,
"format": "<format>"
},
"generated_sizes": [
1
],
"warnings": [
{
"code": "EXAMPLE10",
"message": "Added at the front desk"
}
]
}Validates a proposed own-app display name against Apple's charset, length and reserved-word rules, then makes a best-effort probe of Apple's public iTunes Search API for published apps already using that exact name. The probe is WARNING-ONLY and never blocks: it sees published apps only, so a clean result is reported as no_conflict_found rather than available, and any timeout or error degrades to unknown. The authoritative reservation happens later, when the merchant's App Store Connect key is captured.
Store the name belongs to (also authorises the merchant).
The app display name the merchant has typed.
False when the name fails Apple charset/length/reserved-word rules.
Merchant-readable sentence naming what to change. Null when valid.
likely_taken = a published app already uses this exact name. no_conflict_found = none found, NOT a guarantee. unknown = the probe could not answer; say nothing to the merchant.
likely_takenno_conflict_foundunknownPublished apps holding this exact name. Empty unless likely_taken.
The published app name exactly as Apple returns it.
Who publishes it, a rival bakery reads differently to a global brand.
Alternative names, each already within Apple's 30-character ceiling. Empty unless likely_taken.
When the probe ran (ISO 8601), so a later failure at Apple can be dated against it.
curl -G "https://www.membber.com/api/v1/own-app/name-check" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
--data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066" \
--data-urlencode "name=Example name"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.GET("/api/v1/own-app/name-check", {
params: { query: { store_id: "6659c139-0000-4000-8000-d0c500000066", name: "Example name" } },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.checkOwnAppNameAvailability(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066", name: "Example name")
).ok.body.json
print(response){
"valid": true,
"invalid_reason": "Added at the front desk",
"availability": "likely_taken",
"matches": [
{
"name": "Example name",
"seller": "<seller>"
}
],
"suggestions": [
"<suggestion>"
],
"checked_at": "<checked_at>"
}