# Read many creators in one call (request-body form)

`POST /creators/batch`

Identical to `GET /creators?ids=` in every observable way — same buckets, same cap, same semantics — it exists only because an identifier list can outgrow a URL. Requires `creators:read`.

Full operation definition — parameters, request/response schemas, and examples, fully dereferenced against the OpenAPI document:

```json
{
  "operationId": "postCreatorsBatch",
  "tags": [
    "creators"
  ],
  "summary": "Read many creators in one call (request-body form)",
  "description": "Identical to `GET /creators?ids=` in every observable way — same buckets, same cap, same semantics — it exists only because an identifier list can outgrow a URL. Requires `creators:read`.",
  "x-required-scope": "creators:read",
  "requestBody": {
    "required": true,
    "description": "The POST twin of the GET `?ids=` form — it exists only because an identifier list can outgrow a URL. `ids` follows the same 1–100 cap and three identifier forms; `network`, `asOrg`, and `asProfile` mean exactly what the query parameters of the same names mean.",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "ids": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "The identifiers to look up, 1–100 per request. Each is qualified (`instagram:somehandle`), a post/profile URL, or bare (resolved against `network`).",
              "minItems": 1,
              "maxItems": 100
            },
            "network": {
              "description": "Default network for bare identifiers in `ids` (defaults to `instagram`). Never a filter — a qualified (`instagram:handle`) or URL identifier carries its own network.",
              "type": "string"
            },
            "asOrg": {
              "description": "Names a target Organization to act on, when it differs from your credential's own organization — for a delegated agency/partner relationship.",
              "type": "string"
            },
            "asProfile": {
              "description": "Attribution only — associates this batch's discovery/refresh work with one of your Profiles, resolved within your organization.",
              "type": "string"
            }
          },
          "required": [
            "ids"
          ]
        },
        "examples": {
          "somehandle": {
            "value": {
              "ids": [
                "instagram:somehandle",
                "https://www.instagram.com/p/DEF456/"
              ],
              "network": "instagram"
            }
          }
        }
      }
    }
  },
  "responses": {
    "200": {
      "description": "Always 200 — per-item outcomes are buckets, never per-item HTTP statuses.",
      "headers": {
        "x-request-id": {
          "description": "On every response, success or failure. Quote it when contacting support — it's the fastest way for Aspire to find exactly your request.",
          "schema": {
            "type": "string"
          }
        },
        "Retry-After": {
          "description": "Present iff `fetching` is non-empty — delta-seconds until those entries are worth re-submitting (every fetching entry in one response shares the same instant).",
          "schema": {
            "type": "string"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "channels": {
                      "minItems": 1,
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "network": {
                            "type": "string",
                            "const": "instagram",
                            "description": "The social network this channel belongs to."
                          },
                          "externalId": {
                            "description": "The channel's network-native identifier (Instagram's numeric user id), stable for the account's lifetime.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "username": {
                            "description": "The channel's current @handle.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "followersCount": {
                            "description": "Total number of followers.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "verified": {
                            "description": "Whether the network has verified this channel's identity. Sourced only from a successful Instagram Creator Marketplace lookup — null for a brand/business account (Creator Marketplace doesn't cover them) or when Creator Marketplace credentials aren't configured for the org.",
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "country": {
                            "description": "The channel's country.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "instagram": {
                            "type": "object",
                            "properties": {
                              "name": {
                                "description": "The account's display name (distinct from `username`).",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "biography": {
                                "description": "The account's bio text.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "website": {
                                "description": "The website URL listed on the account's profile.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "profilePictureUrl": {
                                "description": "URL of the account's current profile picture.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "followsCount": {
                                "description": "Number of accounts this creator follows.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "mediaCount": {
                                "description": "Total number of posts on this account.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "gender": {
                                "description": "The creator's gender, when known. Common values are `male`, `female`, and `unknown` (undisclosed), though other values may appear over time.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "ageBucket": {
                                "description": "The age range the creator belongs to (e.g. `18-24`), or `unknown` when undisclosed. Other ranges may appear over time.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "onboardedStatus": {
                                "description": "Whether the creator has been onboarded to the Creator Marketplace.",
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "portfolioUrl": {
                                "description": "URL of the creator's Portfolio.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "email": {
                                "description": "Contact email on file for this creator. Not necessarily verified, and no format validation is applied.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "isPaidPartnershipMessagesEnabled": {
                                "description": "Whether the creator has enabled paid partnership messages through the Instagram Creator Marketplace.",
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "hasBrandPartnershipExperience": {
                                "description": "Whether the creator has branded content or partnership ads collaboration experience in the past year.",
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "pastBrandPartnershipPartners": {
                                "description": "The brands the creator has collaborated with on branded content or partnership ads in the past year.",
                                "items": {
                                  "type": "string"
                                },
                                "type": [
                                  "array",
                                  "null"
                                ]
                              },
                              "badges": {
                                "description": "The badges of the creator. Meta does not publish a closed or confirmed set of possible values — treat as opaque strings, not an enum.",
                                "items": {
                                  "type": "string"
                                },
                                "type": [
                                  "array",
                                  "null"
                                ]
                              },
                              "reach": {
                                "description": "This account's reach metric (distinct accounts that saw its content).",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "hasProfilePic": {
                                "description": "Whether the account currently has a profile picture set.",
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "isPublished": {
                                "description": "Whether the account is published.",
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "creatorEngagedAccounts": {
                                "description": "Number of distinct accounts that engaged with this creator's content.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "reelsInteractionRate": {
                                "description": "Reels interaction rate, as a percentage of reel views (e.g. `7.2` means 7.2%).",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "reelsHookRate": {
                                "description": "Reels hook rate — the percentage of viewers who kept watching past the opening seconds (e.g. `42` means 42%).",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "audienceDemographics": {
                                "description": "Engaged-audience demographics, present only for accounts we hold a live grant with audience-insights scope for. Its internal shape is NOT part of the v1 compatibility promise (D19) — Meta's own payload, passed through opaquely. Meta returns 5 breakdown dimensions: country, city, gender, age, and the combined age,gender. Results may not be exhaustive."
                              }
                            },
                            "required": [
                              "name",
                              "biography",
                              "website",
                              "profilePictureUrl",
                              "followsCount",
                              "mediaCount",
                              "gender",
                              "ageBucket",
                              "onboardedStatus",
                              "portfolioUrl",
                              "email",
                              "isPaidPartnershipMessagesEnabled",
                              "hasBrandPartnershipExperience",
                              "pastBrandPartnershipPartners",
                              "badges",
                              "reach",
                              "hasProfilePic",
                              "isPublished",
                              "creatorEngagedAccounts",
                              "reelsInteractionRate",
                              "reelsHookRate"
                            ]
                          },
                          "updatedAt": {
                            "description": "ISO 8601 timestamp of when this channel's current snapshot was produced — how fresh this document is.",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "network",
                          "externalId",
                          "username",
                          "followersCount",
                          "verified",
                          "country",
                          "instagram",
                          "updatedAt"
                        ]
                      },
                      "description": "This creator's channels. Always at least one. UNORDERED — carries no meaningful index; do not read position as significance. Intended to eventually return every channel a creator owns, not only the ones a search filter matched — today this is always exactly one channel; multi-channel hydration is not yet implemented."
                    },
                    "posts": {
                      "description": "This creator's recent posts, included only when the request asked for `?include=posts`. Absent (not empty) when not requested. Posts are not nested per channel — to attribute a post back to one of `channels`, match its `author.accountId` against that channel's `externalId`.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "network": {
                            "description": "The social network this post is on.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "externalId": {
                            "description": "The post's network-native identifier.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "url": {
                            "description": "The post's public permalink.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "postedAt": {
                            "description": "ISO 8601 timestamp of when the post was published.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "text": {
                            "description": "The post's caption text.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "mediaKind": {
                            "description": "The post's media type — `video`, `image`, or `carousel`.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "likeCount": {
                            "description": "Total like count.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "commentCount": {
                            "description": "Total comment count.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "viewCount": {
                            "description": "Total view count.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "shareCount": {
                            "description": "Total share count.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "saveCount": {
                            "description": "Total save count.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "author": {
                            "type": "object",
                            "properties": {
                              "accountId": {
                                "type": "string",
                                "description": "The post author's network-native account identifier."
                              },
                              "username": {
                                "description": "The post author's @handle.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "followersCount": {
                                "description": "Total number of followers the post author has.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "verified": {
                                "description": "Whether the post author's identity is verified on the network.",
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "country": {
                                "description": "The post author's country.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "accountId",
                              "username",
                              "followersCount",
                              "verified",
                              "country"
                            ],
                            "description": "The post's author — a thin, no-PII summary of the creator account. `author.accountId` is the only way to attribute a post back to one of `Creator.channels` — match it against that channel's `externalId`."
                          }
                        },
                        "required": [
                          "network",
                          "externalId",
                          "url",
                          "postedAt",
                          "text",
                          "mediaKind",
                          "likeCount",
                          "commentCount",
                          "viewCount",
                          "shareCount",
                          "saveCount",
                          "author"
                        ]
                      }
                    }
                  },
                  "required": [
                    "channels"
                  ]
                },
                "description": "Documents we hold — same shape as the single read's 200 body."
              },
              "fetching": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The identifier exactly as submitted."
                    },
                    "retryAfter": {
                      "type": "string",
                      "description": "ISO 8601 instant — every fetching entry in one response shares the same instant, and the response's Retry-After header (present iff this bucket is non-empty) is its delta-seconds twin."
                    }
                  },
                  "required": [
                    "id",
                    "retryAfter"
                  ],
                  "description": "A submitted identifier we don't hold yet — this batch read started (or joined) discovery for it. Re-submit it after Retry-After."
                }
              },
              "unavailable": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The identifier exactly as submitted."
                    },
                    "reason": {
                      "type": "string",
                      "description": "Machine-readable, open vocabulary (additions are non-breaking). `outside-recent-media-window` and `author-unresolved` occur on posts only. `internal-error` means the failure was on our side — `retryable` is true."
                    },
                    "retryable": {
                      "description": "Present, and always true, when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.",
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "reason"
                  ],
                  "description": "A submitted identifier that resolved to 'not obtainable'. Check reason (and retryable) — most values mean stop retrying."
                }
              }
            },
            "required": [
              "data",
              "fetching",
              "unavailable"
            ],
            "description": "The three-bucket batch envelope, returned with HTTP 200 always — per-item outcomes are buckets, never per-item HTTP statuses. Every submitted identifier appears in exactly one bucket. The response's Retry-After header is present iff `fetching` is non-empty."
          },
          "examples": {
            "somehandle": {
              "value": {
                "data": [
                  {
                    "channels": [
                      {
                        "network": "instagram",
                        "externalId": "17841400000000000",
                        "username": "somehandle",
                        "followersCount": 12345,
                        "verified": false,
                        "country": "US",
                        "instagram": {
                          "name": "Some Handle",
                          "biography": "Creator bio goes here.",
                          "website": "https://example.com",
                          "profilePictureUrl": "https://example.com/pic.jpg",
                          "followsCount": 200,
                          "mediaCount": 350,
                          "gender": "female",
                          "ageBucket": "25-34",
                          "onboardedStatus": true,
                          "portfolioUrl": "https://example.com/portfolio",
                          "email": "creator@example.com",
                          "isPaidPartnershipMessagesEnabled": true,
                          "hasBrandPartnershipExperience": true,
                          "pastBrandPartnershipPartners": [
                            "brand-a",
                            "brand-b"
                          ],
                          "badges": [
                            "top-creator"
                          ],
                          "reach": 8500,
                          "hasProfilePic": true,
                          "isPublished": true,
                          "creatorEngagedAccounts": 1362,
                          "reelsInteractionRate": 7.2,
                          "reelsHookRate": 42
                        },
                        "updatedAt": "2026-08-01T00:00:00.000Z"
                      }
                    ]
                  }
                ],
                "fetching": [
                  {
                    "id": "instagram:fetching-handle",
                    "retryAfter": "2026-08-01T00:30:05.000Z"
                  }
                ],
                "unavailable": [
                  {
                    "id": "instagram:gone-handle",
                    "reason": "account-not-discoverable"
                  }
                ]
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "A malformed request — e.g. a batch outside the 1–100 identifier cap, an unrecognized `include` value, `url` and `ids` supplied together, or an unparseable JSON body.",
      "headers": {
        "x-request-id": {
          "description": "On every response, success or failure. Quote it when contacting support — it's the fastest way for Aspire to find exactly your request.",
          "schema": {
            "type": "string"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "The stable, machine-readable error code. Maps 1:1 to the HTTP status."
                  },
                  "message": {
                    "type": "string",
                    "description": "Human prose for logs and error screens. Never parse it."
                  },
                  "details": {
                    "description": "Optional structured extras. Today's one use: a read-miss 404's reason (and retryable, when our fault) — see `details.reason`.",
                    "type": "object",
                    "properties": {
                      "reason": {
                        "type": "string",
                        "description": "Machine-readable, open vocabulary — same values a batch unavailable entry's own `reason` carries."
                      },
                      "retryable": {
                        "description": "Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.",
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "reason"
                    ]
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "description": "The one JSON shape every error response (any status other than 200/202) carries, wrapped under `error` in `apiErrorResponseSchema`."
              }
            },
            "required": [
              "error"
            ],
            "description": "The one JSON shape every error response (any status other than 200/202) carries."
          },
          "example": {
            "error": {
              "code": "invalid-input",
              "message": "ids must contain between 1 and 100 identifiers, got 101"
            }
          }
        }
      }
    },
    "401": {
      "description": "Missing, malformed, expired, or revoked credential.",
      "headers": {
        "x-request-id": {
          "description": "On every response, success or failure. Quote it when contacting support — it's the fastest way for Aspire to find exactly your request.",
          "schema": {
            "type": "string"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "The stable, machine-readable error code. Maps 1:1 to the HTTP status."
                  },
                  "message": {
                    "type": "string",
                    "description": "Human prose for logs and error screens. Never parse it."
                  },
                  "details": {
                    "description": "Optional structured extras. Today's one use: a read-miss 404's reason (and retryable, when our fault) — see `details.reason`.",
                    "type": "object",
                    "properties": {
                      "reason": {
                        "type": "string",
                        "description": "Machine-readable, open vocabulary — same values a batch unavailable entry's own `reason` carries."
                      },
                      "retryable": {
                        "description": "Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.",
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "reason"
                    ]
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "description": "The one JSON shape every error response (any status other than 200/202) carries, wrapped under `error` in `apiErrorResponseSchema`."
              }
            },
            "required": [
              "error"
            ],
            "description": "The one JSON shape every error response (any status other than 200/202) carries."
          },
          "example": {
            "error": {
              "code": "unauthorized",
              "message": "invalid credential"
            }
          }
        }
      }
    },
    "403": {
      "description": "Valid credential, but it lacks the `<resource>:<action>` permission this operation requires (stated in the operation description).",
      "headers": {
        "x-request-id": {
          "description": "On every response, success or failure. Quote it when contacting support — it's the fastest way for Aspire to find exactly your request.",
          "schema": {
            "type": "string"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "The stable, machine-readable error code. Maps 1:1 to the HTTP status."
                  },
                  "message": {
                    "type": "string",
                    "description": "Human prose for logs and error screens. Never parse it."
                  },
                  "details": {
                    "description": "Optional structured extras. Today's one use: a read-miss 404's reason (and retryable, when our fault) — see `details.reason`.",
                    "type": "object",
                    "properties": {
                      "reason": {
                        "type": "string",
                        "description": "Machine-readable, open vocabulary — same values a batch unavailable entry's own `reason` carries."
                      },
                      "retryable": {
                        "description": "Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.",
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "reason"
                    ]
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "description": "The one JSON shape every error response (any status other than 200/202) carries, wrapped under `error` in `apiErrorResponseSchema`."
              }
            },
            "required": [
              "error"
            ],
            "description": "The one JSON shape every error response (any status other than 200/202) carries."
          },
          "example": {
            "error": {
              "code": "forbidden",
              "message": "token lacks creators:read permission"
            }
          }
        }
      }
    },
    "404": {
      "description": "A read-miss (branch on `details.reason` — retry only if `details.retryable` is `true`, never on `message` prose), an unknown `asProfile` (deliberately indistinguishable from a nonexistent one, so slugs are not enumerable), or an unsupported network. `details.reason` is an open vocabulary (additions are non-breaking). Values today: `account-not-discoverable` (creators — terminal; a personal account and a nonexistent handle are indistinguishable), `not-supported-on-network` (the network isn't supported yet — terminal until it ships), `outside-recent-media-window` (posts — terminal), `author-unresolved` (posts), `unparseable-identifier`, and `internal-error` with `details.retryable: true` (our fault — retry after a few minutes).",
      "headers": {
        "x-request-id": {
          "description": "On every response, success or failure. Quote it when contacting support — it's the fastest way for Aspire to find exactly your request.",
          "schema": {
            "type": "string"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "The stable, machine-readable error code. Maps 1:1 to the HTTP status."
                  },
                  "message": {
                    "type": "string",
                    "description": "Human prose for logs and error screens. Never parse it."
                  },
                  "details": {
                    "description": "Optional structured extras. Today's one use: a read-miss 404's reason (and retryable, when our fault) — see `details.reason`.",
                    "type": "object",
                    "properties": {
                      "reason": {
                        "type": "string",
                        "description": "Machine-readable, open vocabulary — same values a batch unavailable entry's own `reason` carries."
                      },
                      "retryable": {
                        "description": "Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.",
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "reason"
                    ]
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "description": "The one JSON shape every error response (any status other than 200/202) carries, wrapped under `error` in `apiErrorResponseSchema`."
              }
            },
            "required": [
              "error"
            ],
            "description": "The one JSON shape every error response (any status other than 200/202) carries."
          },
          "example": {
            "error": {
              "code": "not-found",
              "message": "no creator found for instagram/somehandle",
              "details": {
                "reason": "account-not-discoverable"
              }
            }
          }
        }
      }
    },
    "429": {
      "description": "Over the per-principal request budget (fixed one-minute window; default 60 requests/minute, raisable per Service Account). Rejected requests still count against the window. Honour `Retry-After`.",
      "headers": {
        "x-request-id": {
          "description": "On every response, success or failure. Quote it when contacting support — it's the fastest way for Aspire to find exactly your request.",
          "schema": {
            "type": "string"
          }
        },
        "Retry-After": {
          "description": "Delta-seconds (RFC 9110 §10.2.3), always ≥ 1. The server controls the backoff — polling faster than this burns rate limit and gets the data no sooner.",
          "schema": {
            "type": "string"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "The stable, machine-readable error code. Maps 1:1 to the HTTP status."
                  },
                  "message": {
                    "type": "string",
                    "description": "Human prose for logs and error screens. Never parse it."
                  },
                  "details": {
                    "description": "Optional structured extras. Today's one use: a read-miss 404's reason (and retryable, when our fault) — see `details.reason`.",
                    "type": "object",
                    "properties": {
                      "reason": {
                        "type": "string",
                        "description": "Machine-readable, open vocabulary — same values a batch unavailable entry's own `reason` carries."
                      },
                      "retryable": {
                        "description": "Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.",
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "reason"
                    ]
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "description": "The one JSON shape every error response (any status other than 200/202) carries, wrapped under `error` in `apiErrorResponseSchema`."
              }
            },
            "required": [
              "error"
            ],
            "description": "The one JSON shape every error response (any status other than 200/202) carries."
          },
          "example": {
            "error": {
              "code": "rate-limited",
              "message": "rate limit exceeded (60 requests/minute for this principal)"
            }
          }
        }
      }
    },
    "500": {
      "description": "Our fault. The message is deliberately generic — internal error detail is never exposed. Safe to retry with backoff.",
      "headers": {
        "x-request-id": {
          "description": "On every response, success or failure. Quote it when contacting support — it's the fastest way for Aspire to find exactly your request.",
          "schema": {
            "type": "string"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "The stable, machine-readable error code. Maps 1:1 to the HTTP status."
                  },
                  "message": {
                    "type": "string",
                    "description": "Human prose for logs and error screens. Never parse it."
                  },
                  "details": {
                    "description": "Optional structured extras. Today's one use: a read-miss 404's reason (and retryable, when our fault) — see `details.reason`.",
                    "type": "object",
                    "properties": {
                      "reason": {
                        "type": "string",
                        "description": "Machine-readable, open vocabulary — same values a batch unavailable entry's own `reason` carries."
                      },
                      "retryable": {
                        "description": "Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.",
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "reason"
                    ]
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "description": "The one JSON shape every error response (any status other than 200/202) carries, wrapped under `error` in `apiErrorResponseSchema`."
              }
            },
            "required": [
              "error"
            ],
            "description": "The one JSON shape every error response (any status other than 200/202) carries."
          },
          "example": {
            "error": {
              "code": "internal-error",
              "message": "the request could not be completed"
            }
          }
        }
      }
    },
    "503": {
      "description": "A dependency needed to verify the credential is unreachable — the credential was neither accepted nor rejected. Retry with backoff.",
      "headers": {
        "x-request-id": {
          "description": "On every response, success or failure. Quote it when contacting support — it's the fastest way for Aspire to find exactly your request.",
          "schema": {
            "type": "string"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "The stable, machine-readable error code. Maps 1:1 to the HTTP status."
                  },
                  "message": {
                    "type": "string",
                    "description": "Human prose for logs and error screens. Never parse it."
                  },
                  "details": {
                    "description": "Optional structured extras. Today's one use: a read-miss 404's reason (and retryable, when our fault) — see `details.reason`.",
                    "type": "object",
                    "properties": {
                      "reason": {
                        "type": "string",
                        "description": "Machine-readable, open vocabulary — same values a batch unavailable entry's own `reason` carries."
                      },
                      "retryable": {
                        "description": "Present (and true) only when the failure was on our side rather than a fact about the entity — retry after a few minutes. Absent means terminal: stop retrying.",
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "reason"
                    ]
                  }
                },
                "required": [
                  "code",
                  "message"
                ],
                "description": "The one JSON shape every error response (any status other than 200/202) carries, wrapped under `error` in `apiErrorResponseSchema`."
              }
            },
            "required": [
              "error"
            ],
            "description": "The one JSON shape every error response (any status other than 200/202) carries."
          },
          "example": {
            "error": {
              "code": "unavailable",
              "message": "temporarily unavailable"
            }
          }
        }
      }
    }
  }
}
```
