{
  "openapi": "3.1.0",
  "info": {
    "title": "Laya Studio API",
    "version": "1.0.0",
    "description": "Hosted inference for the open-source Laya decision model. Wire-compatible with the TypeSafe Jev /v1/systemone protocol. Billing: per input token (1 credit = 1 input token, the usage.input_tokens of a successful response), 30% below Jev's list price; 5 free runs per new workspace; failed requests are free. Headers: x-credits-charged, x-free-runs-remaining."
  },
  "servers": [
    {
      "url": "https://api.laya.studio"
    },
    {
      "url": "https://laya.studio"
    }
  ],
  "security": [
    {
      "bearer": []
    }
  ],
  "paths": {
    "/v1/systemone": {
      "post": {
        "operationId": "systemone",
        "summary": "Answer typed questions about a state in one forward pass",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DecisionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Answers with calibrated probabilities",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DecisionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Malformed request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "402": {
            "description": "Free runs used and not enough credits (input tokens) for this request"
          },
          "422": {
            "description": "A question is invalid (unknown type, missing criteria, …)"
          },
          "429": {
            "description": "Rate limited — see Retry-After"
          },
          "503": {
            "description": "Inference temporarily unavailable — retry with backoff"
          }
        }
      }
    },
    "/v1/ask": {
      "post": {
        "operationId": "ask",
        "summary": "Plain words in: an LLM plans the questions, Laya answers them",
        "description": "Send what you want to know in plain words, with the text to judge. A planner (Mercury 2.5 via phi-cloud; a Swiss-resident model when the request is Swiss-only) writes typed questions and calls decide; Laya answers them with calibrated probabilities and the reply is built from those numbers. Billed: the decision's input tokens (+15% when Swiss-only) plus the planner's tokens: 2 credits per prompt token and 7 per completion token on Mercury, 12 and 23 on the Swiss planner (Gemma-4 31B), or one free run.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "prompt"
                ],
                "properties": {
                  "prompt": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The reply, the plan (reusable with /v1/systemone), the answers and the planner usage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "reply": {
                      "type": "string"
                    },
                    "plan": {
                      "type": "object",
                      "properties": {
                        "state": {},
                        "questions": {
                          "type": "object"
                        }
                      }
                    },
                    "answers": {
                      "type": "object"
                    },
                    "usage": {
                      "type": "object"
                    },
                    "llm": {
                      "type": "object",
                      "properties": {
                        "model": {
                          "type": "string"
                        },
                        "region": {
                          "type": "string"
                        },
                        "input_tokens": {
                          "type": "integer"
                        },
                        "output_tokens": {
                          "type": "integer"
                        },
                        "credits": {
                          "type": "integer"
                        }
                      }
                    },
                    "credits_charged": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing prompt"
          },
          "402": {
            "description": "Free runs used and the balance cannot cover the estimate"
          },
          "422": {
            "description": "The planner could not turn the request into questions (nothing charged)"
          },
          "503": {
            "description": "Planner or inference unavailable (nothing charged)"
          }
        }
      }
    },
    "/v1/systemone/batch": {
      "post": {
        "operationId": "systemoneBatch",
        "summary": "Up to 64 decisions in one call",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "requests"
                ],
                "properties": {
                  "requests": {
                    "type": "array",
                    "maxItems": 64,
                    "items": {
                      "$ref": "#/components/schemas/DecisionRequest"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result (or {error}) per request, in order"
          },
          "400": {
            "description": "Malformed request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "402": {
            "description": "Free runs used and not enough credits (input tokens) for this request"
          },
          "422": {
            "description": "A question is invalid (unknown type, missing criteria, …)"
          },
          "429": {
            "description": "Rate limited — see Retry-After"
          },
          "503": {
            "description": "Inference temporarily unavailable — retry with backoff"
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "operationId": "models",
        "summary": "List served checkpoints",
        "security": [],
        "responses": {
          "200": {
            "description": "Models"
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "usage",
        "summary": "Credit balance and 30-day usage",
        "responses": {
          "200": {
            "description": "Usage"
          },
          "401": {
            "description": "Missing or invalid API key"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "lsk_live_… key from the dashboard"
      }
    },
    "schemas": {
      "Question": {
        "type": "object",
        "required": [
          "type",
          "instructions"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "choice",
              "score",
              "noul"
            ]
          },
          "instructions": {
            "type": "string",
            "description": "What the model should decide, in plain language."
          },
          "criteria": {
            "description": "choice: object label → description, or array of labels. score: array of level descriptions (index 0 first). noul: optional {\"true\": \"...\", \"false\": \"...\"}.",
            "oneOf": [
              {
                "type": "object",
                "additionalProperties": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          }
        }
      },
      "DecisionRequest": {
        "type": "object",
        "required": [
          "questions"
        ],
        "properties": {
          "state": {
            "description": "The input to decide about: a string, a JSON object, or a list of conversation turns."
          },
          "questions": {
            "type": "object",
            "maxProperties": 32,
            "additionalProperties": {
              "$ref": "#/components/schemas/Question"
            }
          },
          "model": {
            "type": "string",
            "enum": [
              "english",
              "multilingual",
              "typed-decisions"
            ],
            "description": "Pin a checkpoint. Omit to route automatically by script and language. Unknown ids (e.g. Jev model names) are ignored."
          },
          "lang": {
            "type": "string",
            "maxLength": 16,
            "description": "Optional language hint such as \"en\" or \"de-CH\"; overrides detection."
          }
        }
      },
      "Answer": {
        "oneOf": [
          {
            "type": "object",
            "title": "ChoiceAnswer",
            "properties": {
              "type": {
                "const": "choice"
              },
              "choice": {
                "type": "string"
              },
              "probabilities": {
                "type": "object",
                "additionalProperties": {
                  "type": "number"
                }
              },
              "confidence": {
                "type": "number",
                "description": "1 − H(p)/log k (normalised-entropy confidence)."
              },
              "action": {
                "type": "object",
                "properties": {
                  "act_probability": {
                    "type": "number"
                  }
                }
              }
            }
          },
          {
            "type": "object",
            "title": "ScoreAnswer",
            "properties": {
              "type": {
                "const": "score"
              },
              "score": {
                "type": "number",
                "description": "Expected level index."
              },
              "legend": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              },
              "probabilities": {
                "type": "object",
                "additionalProperties": {
                  "type": "number"
                }
              },
              "confidence": {
                "type": "number"
              },
              "action": {
                "type": "object",
                "properties": {
                  "act_probability": {
                    "type": "number"
                  }
                }
              }
            }
          },
          {
            "type": "object",
            "title": "NoulAnswer",
            "properties": {
              "type": {
                "const": "noul"
              },
              "noul": {
                "type": "number",
                "description": "P(true)."
              },
              "confidence": {
                "type": "number"
              },
              "action": {
                "type": "object",
                "properties": {
                  "act_probability": {
                    "type": "number"
                  }
                }
              }
            }
          }
        ]
      },
      "DecisionResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "answers": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/Answer"
            }
          },
          "usage": {
            "type": "object",
            "properties": {
              "input_tokens": {
                "type": "integer"
              },
              "output_tokens": {
                "type": "integer",
                "const": 0
              }
            }
          },
          "routing": {
            "type": "object",
            "properties": {
              "model": {
                "type": "string"
              },
              "reason": {
                "type": "string"
              },
              "repo": {
                "type": "string"
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}