{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Goblin3D API","version":"1.0.0","summary":"Asynchronous text-to-3D generation for Goblin3D subscribers.","description":"Create textured 3D assets from text prompts, poll generation status, and download completed GLB files. Generation operations require a Goblin3D Bearer API key and an active Pro or Max subscription.","contact":{"name":"Goblin3D Support","email":"support@goblin3d.ai","url":"https://goblin3d.ai/en/support"},"termsOfService":"https://goblin3d.ai/en/terms"},"servers":[{"url":"https://goblin3d.ai","description":"Production"}],"externalDocs":{"description":"Goblin3D developer guide","url":"https://goblin3d.ai/en/developers"},"tags":[{"name":"Discovery","description":"Public, authentication-free API metadata."},{"name":"Generations","description":"Authenticated text-to-3D generation jobs owned by the API-key subscriber."}],"x-agent-instructions":{"whenToUse":"Use the API when a user explicitly wants a textured 3D asset generated from a text prompt and can review the result.","workflow":["Confirm the user has an active Pro or Max subscription and a server-side API key.","Create one generation with a unique Idempotency-Key.","Poll the returned generation URL while status is queued or processing, respecting Retry-After.","Download the GLB only after status is succeeded, then ask the user to review it before production use or publication."],"constraints":["Never expose a Bearer API key in client-side code, logs, or public repositories.","Do not promise production-ready topology, rigging, or a deterministic visual result.","Do not submit repeated generations without explicit user intent because each accepted job can consume credits."]},"x-versioning-policy":{"currentMajor":"v1","strategy":"Major API versions are encoded in the URL path.","policyUrl":"https://goblin3d.ai/en/developers#versioning","compatibility":"Additive fields and endpoints may be introduced within v1. Clients should ignore unknown response fields. Breaking request or response changes require a new major path.","deprecation":"No v1 operation is currently deprecated. Future deprecations will be marked in OpenAPI and with an RFC 9745 Deprecation header. A migration guide and RFC 8594 Sunset header will announce removal at least 90 days in advance."},"x-deprecation-policy":{"url":"https://goblin3d.ai/en/developers#versioning","minimumNoticeDays":90,"signals":["OpenAPI deprecated flag","Deprecation header","Sunset header"]},"paths":{"/api/v1/capabilities":{"get":{"operationId":"getApiCapabilities","tags":["Discovery"],"summary":"Get public API capabilities","description":"Returns the current API version, documentation links, authentication requirements, generation modes, output format, and agent-use guidance. No API key is required.","security":[],"responses":{"200":{"description":"Current public capabilities.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Capabilities"}}}},"default":{"$ref":"#/components/responses/ApiErrorResponse"}}}},"/api/v1/generations":{"get":{"operationId":"listGenerations","tags":["Generations"],"summary":"List generations","description":"Lists generation jobs owned by the subscriber associated with the Bearer API key.","security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","description":"One-based page number. Invalid values fall back to 1.","required":false,"schema":{"type":"integer","minimum":1,"maximum":10000,"default":1}},{"name":"page_size","in":"query","description":"Number of results per page.","required":false,"schema":{"type":"integer","enum":[12,20,40],"default":20}}],"responses":{"200":{"description":"A page of subscriber-owned generations.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationList"}}}},"401":{"$ref":"#/components/responses/AuthenticationError"},"403":{"$ref":"#/components/responses/PermissionError"},"429":{"$ref":"#/components/responses/RateLimitError"},"503":{"$ref":"#/components/responses/UnavailableError"},"default":{"$ref":"#/components/responses/ApiErrorResponse"}}},"post":{"operationId":"createGeneration","tags":["Generations"],"summary":"Create a text-to-3D generation","description":"Starts one asynchronous textured 3D generation. An accepted request can consume credits. Use a unique Idempotency-Key when the same logical request may be retried.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","description":"Recommended unique key for safe retries of the same logical request.","required":false,"schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[A-Za-z0-9:_-]{8,128}$"},"example":"generation_demo_001"}],"requestBody":{"required":true,"description":"A text prompt and an optional quality preset.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGenerationRequest"},"examples":{"standard":{"summary":"Stylized game asset","value":{"prompt":"A stylized forest guardian with moss armor","quality":"standard"}}}}}},"responses":{"200":{"description":"A terminal generation returned by a replayed idempotent request.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Idempotency-Replayed":{"description":"Present and true when an existing result was replayed.","schema":{"type":"string","const":"true"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generation"}}}},"202":{"description":"Generation accepted for asynchronous processing.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"description":"Absolute URL for polling this generation.","schema":{"type":"string","format":"uri"}},"Idempotency-Replayed":{"description":"Present and true when an active generation was replayed.","schema":{"type":"string","const":"true"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generation"}}}},"400":{"$ref":"#/components/responses/InvalidRequestError"},"401":{"$ref":"#/components/responses/AuthenticationError"},"402":{"$ref":"#/components/responses/BillingError"},"403":{"$ref":"#/components/responses/PermissionError"},"409":{"$ref":"#/components/responses/ConflictError"},"413":{"$ref":"#/components/responses/InvalidRequestError"},"415":{"$ref":"#/components/responses/InvalidRequestError"},"429":{"$ref":"#/components/responses/RateLimitError"},"503":{"$ref":"#/components/responses/UnavailableError"},"default":{"$ref":"#/components/responses/ApiErrorResponse"}}}},"/api/v1/generations/{id}":{"get":{"operationId":"getGeneration","tags":["Generations"],"summary":"Get generation status","description":"Returns a subscriber-owned generation. While status is queued or processing, wait for the Retry-After duration before polling again.","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/GenerationId"}],"responses":{"200":{"description":"Current generation state.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"description":"Seconds to wait before polling again when work is pending.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generation"}}}},"401":{"$ref":"#/components/responses/AuthenticationError"},"403":{"$ref":"#/components/responses/PermissionError"},"404":{"$ref":"#/components/responses/NotFoundError"},"429":{"$ref":"#/components/responses/RateLimitError"},"503":{"$ref":"#/components/responses/UnavailableError"},"default":{"$ref":"#/components/responses/ApiErrorResponse"}}}},"/api/v1/generations/{id}/download":{"get":{"operationId":"downloadGeneration","tags":["Generations"],"summary":"Download a completed GLB","description":"Returns a short-lived redirect to the protected GLB for a succeeded generation owned by the subscriber. Clients should follow the redirect without forwarding the Goblin3D Bearer token to a different host.","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/GenerationId"}],"responses":{"302":{"description":"Short-lived redirect to the completed GLB file.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"description":"Short-lived protected model URL.","required":true,"schema":{"type":"string","format":"uri"}}}},"401":{"$ref":"#/components/responses/AuthenticationError"},"403":{"$ref":"#/components/responses/PermissionError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"$ref":"#/components/responses/ConflictError"},"429":{"$ref":"#/components/responses/RateLimitError"},"503":{"$ref":"#/components/responses/UnavailableError"},"default":{"$ref":"#/components/responses/ApiErrorResponse"}}}}},"components":{"headers":{"RateLimitLimit":{"description":"Maximum requests permitted by the active rate-limit policy.","schema":{"type":"integer","minimum":1}},"RateLimitRemaining":{"description":"Requests remaining in the active rate-limit window.","schema":{"type":"integer","minimum":0}},"RateLimitReset":{"description":"Seconds until the active rate-limit window resets.","schema":{"type":"integer","minimum":0}},"RateLimitPolicy":{"description":"Applied request limit and window in seconds.","schema":{"type":"string","pattern":"^[0-9]+;w=[0-9]+$","example":"120;w=60"}}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Goblin3D API key","description":"Server-side API key created at https://goblin3d.ai/en/api-access. Never expose this secret in client-side code."}},"parameters":{"GenerationId":{"name":"id","in":"path","required":true,"description":"Generation UUID returned by createGeneration.","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"}}},"responses":{"ApiErrorResponse":{"description":"A structured API error with a concrete resolution, documentation link, and request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"InvalidRequestError":{"description":"The request body, parameter, or content type is invalid.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"AuthenticationError":{"description":"The Bearer API key is missing or invalid.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"WWW-Authenticate":{"description":"Bearer authentication challenge.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"BillingError":{"description":"The account does not have enough credits for the request.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"PermissionError":{"description":"An active Pro or Max subscription is required.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"NotFoundError":{"description":"The generation does not exist or is not owned by the subscriber.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"ConflictError":{"description":"The generation is not ready for this operation or an idempotency key was reused with different input.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"RateLimitError":{"description":"Too many requests. Wait for Retry-After before retrying.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"UnavailableError":{"description":"The API or authorization service is temporarily unavailable.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"schemas":{"Capabilities":{"type":"object","additionalProperties":false,"required":["object","name","version","api_version","base_url","documentation_url","openapi_url","authentication","generation","agent_guidance"],"properties":{"object":{"type":"string","const":"capabilities"},"name":{"type":"string","const":"Goblin3D API"},"version":{"type":"string","const":"v1"},"api_version":{"type":"string","const":"v1"},"base_url":{"type":"string","format":"uri"},"documentation_url":{"type":"string","format":"uri"},"openapi_url":{"type":"string","format":"uri"},"authentication":{"type":"object","required":["type","required_for","api_key_management_url","access"],"properties":{"type":{"type":"string","const":"bearer"},"required_for":{"type":"array","items":{"type":"string"}},"api_key_management_url":{"type":"string","format":"uri"},"access":{"type":"string"}}},"generation":{"type":"object","required":["mode","output_format","qualities","status_lifecycle","asynchronous"],"properties":{"mode":{"type":"string","const":"text-to-3d"},"output_format":{"type":"string","const":"glb"},"qualities":{"type":"array","items":{"type":"string","enum":["standard","high"]}},"status_lifecycle":{"type":"array","items":{"type":"string","enum":["queued","processing","succeeded","failed"]}},"asynchronous":{"type":"boolean","const":true}}},"agent_guidance":{"type":"object","required":["use_when","avoid_when","secret_handling"],"properties":{"use_when":{"type":"string"},"avoid_when":{"type":"string"},"secret_handling":{"type":"string"}}}}},"CreateGenerationRequest":{"type":"object","additionalProperties":false,"required":["prompt"],"properties":{"prompt":{"type":"string","minLength":3,"maxLength":20000,"description":"Text description of the desired 3D asset."},"quality":{"type":"string","enum":["standard","high"],"default":"standard","description":"Generation quality preset."}}},"Generation":{"type":"object","additionalProperties":false,"required":["id","object","status","title","created_at","updated_at","output","error"],"properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","const":"generation"},"status":{"type":"string","enum":["queued","processing","succeeded","failed"]},"title":{"type":"string"},"created_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"updated_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"output":{"oneOf":[{"$ref":"#/components/schemas/GenerationOutput"},{"type":"null"}]},"error":{"oneOf":[{"$ref":"#/components/schemas/GenerationFailure"},{"type":"null"}]}}},"GenerationOutput":{"type":"object","additionalProperties":false,"required":["format","model_url"],"properties":{"format":{"type":"string","const":"glb"},"model_url":{"type":"string","format":"uri"}}},"GenerationFailure":{"type":"object","additionalProperties":false,"required":["code","message"],"properties":{"code":{"type":"string","const":"GENERATION_FAILED"},"message":{"type":"string"}}},"GenerationList":{"type":"object","additionalProperties":false,"required":["object","data","pagination"],"properties":{"object":{"type":"string","const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Generation"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"Pagination":{"type":"object","additionalProperties":false,"required":["page","page_size","total_count","total_pages"],"properties":{"page":{"type":"integer","minimum":1},"page_size":{"type":"integer","minimum":0},"total_count":{"type":"integer","minimum":0},"total_pages":{"type":"integer","minimum":1}}},"ErrorEnvelope":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"$ref":"#/components/schemas/ApiError"}}},"ApiError":{"type":"object","additionalProperties":false,"required":["type","code","message","param","resolution","documentation_url","request_id"],"properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"param":{"oneOf":[{"type":"string"},{"type":"null"}]},"resolution":{"type":"string","description":"A concrete next step that can resolve or safely retry the error."},"documentation_url":{"type":"string","format":"uri"},"request_id":{"type":"string","format":"uuid","description":"Identifier to include when contacting support."}}}}}}