{"openapi":"3.1.0","info":{"title":"Photo2Skin public API","version":"0.1.0","description":"Read-only and free: the Minecraft skin library, the skin grabber and prices. To create skins, worlds or pixel art for a person, use the MCP server at https://mcp.photo2skin.com/mcp — see https://app.photo2skin.com/developers."},"servers":[{"url":"https://app.photo2skin.com/api"}],"paths":{"/credit-costs":{"get":{"tags":["pricing"],"summary":"Credit Costs","description":"What each kind of generation costs, and which modes can be used.\n\nUnauthenticated: the generate/text/pixelate pages show a price before sign-in. The skin prices\ndepend on who asks, exactly as ``generation_cost`` charges them — the iOS app is quoted its\nown prices in ``skin_photo`` / ``skin_text``, every other caller the ultra price there.\n\nServing this rather than letting clients hold their own copy is the point — the same four\nnumbers used to be written out again in the web app, so a price change meant editing two\napps and the two could silently disagree. ``ultra_available`` is false when that pipeline is\ndisabled or unconfigured, so the UI hides the option instead of letting the click 503.","operationId":"credit_costs_credit_costs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditCostsResponse"}}}}}}},"/pricing":{"get":{"tags":["pricing"],"summary":"Pricing","description":"Plans, credit packs and what each generation costs — the public pricing page's data.\n\nUnauthenticated, priced at the caller's country (CF-IPCountry) like the paywall it mirrors.\nRead-only: buying still happens on the website's paywall, signed in.","operationId":"pricing_pricing_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingResponse"}}}}}}},"/library/skins":{"get":{"tags":["library"],"summary":"List Skins","operationId":"list_skins_library_skins_get","parameters":[{"name":"sort","in":"query","required":false,"schema":{"enum":["newest","views","likes","downloads","trending"],"type":"string","default":"newest","title":"Sort"}},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tag"}},{"name":"colour","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},{"type":"null"}],"title":"Colour"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Q"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":1,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkinListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/tags":{"get":{"tags":["library"],"summary":"List Tags","operationId":"list_tags_library_tags_get","parameters":[{"name":"only_indexable","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Only Indexable"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TagRef"},"title":"Response List Tags Library Tags Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/skins/{public_id}":{"get":{"tags":["library"],"summary":"Get Skin","operationId":"get_skin_library_skins__public_id__get","parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkinDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/skins/{public_id}/similar":{"get":{"tags":["library"],"summary":"Get Similar","description":"The look-alike rail, paged.\n\n`offset` is how many the caller is already showing. The ranking is deterministic, so a longer\nlist is a prefix-stable extension of a shorter one — which is why paging can be a slice of a\ndeeper query rather than a cursor the client has to carry.","operationId":"get_similar_library_skins__public_id__similar_get","parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":24,"minimum":1,"default":18,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":60,"minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SkinCard"},"title":"Response Get Similar Library Skins  Public Id  Similar Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/skins/{public_id}/{asset}":{"get":{"tags":["library"],"summary":"Get Asset","description":"A pre-rendered artifact. Immutable, so a live one is cached for a year.\n\nA *pending* skin's render is served too, because its author has to be able to see the thing\nthey just uploaded sitting in the review queue. That is the same trade the share links make:\nthe public id is unguessable and the skin is listed nowhere but its author's own shelf. It is\nnever cached, and ``hidden`` still 404s outright — a takedown has to bite immediately.","operationId":"get_asset_library_skins__public_id___asset__get","parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"}},{"name":"asset","in":"path","required":true,"schema":{"type":"string","title":"Asset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/grab/{query}":{"get":{"tags":["library"],"summary":"Grab Player Skin","description":"The skin a Minecraft account is currently wearing, by username or UUID.\n\nPublic game data — no Minecraft API approval needed, and none of it is ours: the response\nattributes the skin to the player it came from and links to the catalogue only when we\nalready hold the same pixels.","operationId":"grab_player_skin_library_grab__query__get","parameters":[{"name":"query","in":"path","required":true,"schema":{"type":"string","title":"Query"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GrabbedSkinResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/creators/{username}":{"get":{"tags":["library"],"summary":"Get Creator","operationId":"get_creator_library_creators__username__get","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string","title":"Username"}},{"name":"space","in":"query","required":false,"schema":{"anyOf":[{"const":"bedrock","type":"string"},{"type":"null"}],"description":"Handle space to look in; omit for the bare /player/{name} space","title":"Space"},"description":"Handle space to look in; omit for the bare /player/{name} space"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatorProfile"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/creators/{username}/skins":{"get":{"tags":["library"],"summary":"Get Creator Skins","operationId":"get_creator_skins_library_creators__username__skins_get","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string","title":"Username"}},{"name":"tab","in":"query","required":false,"schema":{"enum":["added","liked","saved"],"type":"string","default":"added","title":"Tab"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SkinCard"},"title":"Response Get Creator Skins Library Creators  Username  Skins Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/leaderboard":{"get":{"tags":["library"],"summary":"Get Leaderboard","operationId":"get_leaderboard_library_leaderboard_get","parameters":[{"name":"period","in":"query","required":false,"schema":{"enum":["week","month","all"],"type":"string","default":"all","title":"Period"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LeaderboardRow"},"title":"Response Get Leaderboard Library Leaderboard Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"CreatorProfile":{"properties":{"username":{"type":"string","title":"Username"},"avatar_skin_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Skin Id"},"showcase_skin_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Showcase Skin Id"},"avatar_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Url"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"level":{"type":"integer","title":"Level","default":0},"block":{"type":"string","title":"Block","default":"dirt"},"xp":{"type":"integer","title":"Xp","default":0},"socials":{"additionalProperties":{"type":"string"},"type":"object","title":"Socials"},"social_urls":{"additionalProperties":{"type":"string"},"type":"object","title":"Social Urls"},"follower_count":{"type":"integer","title":"Follower Count","default":0},"following_count":{"type":"integer","title":"Following Count","default":0},"skin_count":{"type":"integer","title":"Skin Count","default":0},"linked":{"type":"boolean","title":"Linked","description":"Handle is a verified Minecraft account","default":false},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform","description":"'java' or 'bedrock'"},"verified_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verified Name"},"profile_path":{"type":"string","title":"Profile Path","default":"/"},"joined_at":{"type":"string","format":"date-time","title":"Joined At"},"following":{"type":"boolean","title":"Following","description":"Whether the caller follows them","default":false}},"type":"object","required":["username","joined_at"],"title":"CreatorProfile"},"CreatorRef":{"properties":{"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username","description":"Bare-space profile handle"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"level":{"type":"integer","title":"Level","description":"Index into the block ladder (0 = dirt)","default":0},"block":{"type":"string","title":"Block","description":"Block name for the level badge","default":"dirt"},"linked":{"type":"boolean","title":"Linked","description":"Handle is a verified Minecraft account","default":false},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform","description":"'java' or 'bedrock'"},"verified_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verified Name"},"profile_path":{"type":"string","title":"Profile Path","default":"/"},"avatar_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Url"},"avatar_skin_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Skin Id"}},"type":"object","title":"CreatorRef","description":"How a person is named in public.\n\n``username`` is the profile handle and URL, and every account has one. ``linked`` says whether\nit is a *verified Minecraft name* rather than a generated one — that is the badge, and it is\nthe only thing linking changes about someone's standing here."},"CreditCostsResponse":{"properties":{"skin_photo":{"type":"integer","title":"Skin Photo","description":"Credits for POST /skins/photo for the caller asking: the iOS app pays its own everyone else pays ultra"},"skin_text":{"type":"integer","title":"Skin Text","description":"Credits for POST /skins/text, priced like skin_photo"},"pixelation":{"type":"integer","title":"Pixelation","description":"Credits for POST /pixelations"},"ultra":{"type":"integer","title":"Ultra","description":"Credits for a paid skin from any caller but the iOS app"},"map_base":{"type":"number","title":"Map Base","description":"Flat credits added before the per-km² rate — the fixed cost of any map, however small"},"map_per_km2":{"type":"number","title":"Map Per Km2","description":"Credits per km² of map area, added on top of map_base, before the floor and ceiling below"},"map_min":{"type":"integer","title":"Map Min","description":"Fewest credits a map world can cost"},"map_max":{"type":"integer","title":"Map Max","description":"Most credits a map world can cost"},"ultra_available":{"type":"boolean","title":"Ultra Available","description":"False when the ultra pipeline is disabled or unconfigured — hide the option rather than let the request fail"},"maps_available":{"type":"boolean","title":"Maps Available","description":"False when map generation is disabled — the UI hides the option"},"map_max_area_km2":{"type":"number","title":"Map Max Area Km2","description":"Largest area a single map world may cover, in square kilometres"},"map_max_area_km2_bedrock":{"type":"number","title":"Map Max Area Km2 Bedrock","description":"Largest area a phone/tablet/console (Bedrock) world may cover. Equal to map_max_area_km2 unless the server has lowered this edition on its own; gate on whichever is smaller"},"map_retention_days":{"type":"integer","title":"Map Retention Days","description":"Days a built world is kept before its file is deleted (0 = kept forever). Clients tell the user before they spend credits"},"map_timeout_s":{"type":"integer","title":"Map Timeout S","description":"How long the server will let one world build before it gives up and refunds. Clients poll past this, so the reason they show is the server's own, not a guess"}},"type":"object","required":["skin_photo","skin_text","pixelation","ultra","map_base","map_per_km2","map_min","map_max","ultra_available","maps_available","map_max_area_km2","map_max_area_km2_bedrock","map_retention_days","map_timeout_s"],"title":"CreditCostsResponse","description":"The server-owned price list. Clients render prices from this, never from their own copy."},"GrabbedSkinResponse":{"properties":{"username":{"type":"string","title":"Username"},"uuid":{"type":"string","title":"Uuid"},"model":{"type":"string","title":"Model"},"skin_png":{"type":"string","title":"Skin Png","description":"Base64 PNG, exactly as Mojang serves it"},"texture_url":{"type":"string","title":"Texture Url"},"in_library":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"In Library","description":"Public id of the catalogue entry for these exact pixels, when we hold one"}},"type":"object","required":["username","uuid","model","skin_png","texture_url"],"title":"GrabbedSkinResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LeaderboardRow":{"properties":{"rank":{"type":"integer","title":"Rank"},"creator":{"$ref":"#/components/schemas/CreatorRef"},"score":{"type":"integer","title":"Score"},"skin_count":{"type":"integer","title":"Skin Count","default":0}},"type":"object","required":["rank","creator","score"],"title":"LeaderboardRow"},"PricingResponse":{"properties":{"plans":{"items":{"$ref":"#/components/schemas/WebPaywallPlan"},"type":"array","title":"Plans"},"packs":{"items":{"$ref":"#/components/schemas/WebPaywallPack"},"type":"array","title":"Packs","description":"Credit top-ups, sold to subscribers only"},"currency":{"type":"string","title":"Currency","description":"Currency of every *_cents field","default":"usd"},"costs":{"$ref":"#/components/schemas/CreditCostsResponse","description":"What each generation spends, in credits"}},"type":"object","required":["plans","packs","costs"],"title":"PricingResponse"},"SkinCard":{"properties":{"id":{"type":"string","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"model":{"type":"string","title":"Model"},"views":{"type":"integer","title":"Views"},"likes":{"type":"integer","title":"Likes"},"downloads":{"type":"integer","title":"Downloads"},"comments":{"type":"integer","title":"Comments"},"wearers":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Wearers","description":"Players wearing this skin; null when unknown, never 0-as-unknown"},"trending":{"type":"boolean","title":"Trending","default":false},"is_new":{"type":"boolean","title":"Is New","default":false},"palette":{"items":{"type":"string"},"type":"array","title":"Palette","description":"Up to 5 hex colours for the strip"},"author":{"anyOf":[{"$ref":"#/components/schemas/CreatorRef"},{"type":"null"}]},"liked":{"type":"boolean","title":"Liked","default":false},"saved":{"type":"boolean","title":"Saved","default":false},"status":{"type":"string","title":"Status","default":"live"},"source_generation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Generation Id"},"skin_png_url":{"type":"string","title":"Skin Png Url","description":"The 64x64 skin PNG, ready to upload to Minecraft","default":""},"render_url":{"type":"string","title":"Render Url","description":"A full-body render of the skin (WebP)","default":""},"page_url":{"type":"string","title":"Page Url","description":"The skin's page on the website","default":""}},"type":"object","required":["id","slug","name","model","views","likes","downloads","comments"],"title":"SkinCard","description":"What a grid card needs — and nothing more. No palette blob, no description, no tags."},"SkinDetail":{"properties":{"id":{"type":"string","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"model":{"type":"string","title":"Model"},"views":{"type":"integer","title":"Views"},"likes":{"type":"integer","title":"Likes"},"downloads":{"type":"integer","title":"Downloads"},"comments":{"type":"integer","title":"Comments"},"wearers":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Wearers","description":"Players wearing this skin; null when unknown, never 0-as-unknown"},"trending":{"type":"boolean","title":"Trending","default":false},"is_new":{"type":"boolean","title":"Is New","default":false},"palette":{"items":{"type":"string"},"type":"array","title":"Palette","description":"Up to 5 hex colours for the strip"},"author":{"anyOf":[{"$ref":"#/components/schemas/CreatorRef"},{"type":"null"}]},"liked":{"type":"boolean","title":"Liked","default":false},"saved":{"type":"boolean","title":"Saved","default":false},"status":{"type":"string","title":"Status","default":"live"},"source_generation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Generation Id"},"skin_png_url":{"type":"string","title":"Skin Png Url","description":"The 64x64 skin PNG, ready to upload to Minecraft","default":""},"render_url":{"type":"string","title":"Render Url","description":"A full-body render of the skin (WebP)","default":""},"page_url":{"type":"string","title":"Page Url","description":"The skin's page on the website","default":""},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"texture_hash":{"type":"string","title":"Texture Hash","description":"SHA-256 of the normalised pixels — the skin's identity"},"full_palette":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Full Palette"},"tags":{"items":{"$ref":"#/components/schemas/TagRef"},"type":"array","title":"Tags"},"source":{"type":"string","title":"Source"},"first_seen_player":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Seen Player"},"indexable":{"type":"boolean","title":"Indexable","default":false},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"author_following":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Author Following"},"can_tag":{"type":"boolean","title":"Can Tag","default":false},"worn_by":{"items":{"$ref":"#/components/schemas/CreatorRef"},"type":"array","title":"Worn By"},"worn_by_total":{"type":"integer","title":"Worn By Total","description":"All linked wearers; worn_by holds the first few","default":0}},"type":"object","required":["id","slug","name","model","views","likes","downloads","comments","texture_hash","source"],"title":"SkinDetail"},"SkinListResponse":{"properties":{"skins":{"items":{"$ref":"#/components/schemas/SkinCard"},"type":"array","title":"Skins"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"pages":{"type":"integer","title":"Pages"}},"type":"object","required":["skins","total","page","pages"],"title":"SkinListResponse"},"TagRef":{"properties":{"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"icon":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Icon"},"intro":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Intro","description":"Editorial copy for the category page"},"skin_count":{"type":"integer","title":"Skin Count"},"indexable":{"type":"boolean","title":"Indexable","default":false},"pending":{"type":"boolean","title":"Pending","default":false}},"type":"object","required":["slug","name","skin_count"],"title":"TagRef"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WebPaywallIntro":{"properties":{"price_cents":{"type":"integer","title":"Price Cents"},"credits":{"type":"integer","title":"Credits"}},"type":"object","required":["price_cents","credits"],"title":"WebPaywallIntro"},"WebPaywallPack":{"properties":{"name":{"type":"string","title":"Name"},"price_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Cents"},"credits":{"type":"integer","title":"Credits"},"highlight":{"type":"boolean","title":"Highlight","default":false}},"type":"object","required":["name","price_cents","credits"],"title":"WebPaywallPack"},"WebPaywallPlan":{"properties":{"name":{"type":"string","title":"Name"},"billing_period":{"type":"string","enum":["week","month","year"],"title":"Billing Period"},"price_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Cents"},"credits":{"type":"integer","title":"Credits"},"highlight":{"type":"boolean","title":"Highlight","default":false},"intro":{"anyOf":[{"$ref":"#/components/schemas/WebPaywallIntro"},{"type":"null"}]},"compare_at_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Compare At Cents"}},"type":"object","required":["name","billing_period","price_cents","credits"],"title":"WebPaywallPlan"}}}}