{
  "openapi": "3.1.1",
  "info": {
    "title": "CSV/Excel Chart Studio API",
    "version": "1.0.0",
    "summary": "Turn CSV, TSV or Excel data into line, bar, pie, scatter or histogram charts with SVG/PNG export.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://csvexcelchartstudio.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Turn CSV, TSV or Excel data into line, bar, pie, scatter or histogram charts with SVG/PNG export.",
        "description": "Upload a CSV, TSV or XLSX file (up to 20 MB) or paste a table. The studio detects numbers, dates and categories, lets you pick the chart type, X/Y columns, a grouping column, aggregation (sum, average, count …), sorting and top-N, and returns an accessible SVG chart with SVG and PNG downloads plus the data table behind it.\n\nMethodology:\n- The upload is identified by its content: XLSX (a ZIP container) is unpacked with a built-in reader (shared strings, number formats for dates, cached formula values of the chosen sheet); everything else is read as UTF-8 text (Windows-1252 as fallback) and split with the delimiter that gives the most consistent column count.\n- Each column is classified as number, date or text when at least 90 % of its non-empty cells parse that way. Numbers may use thousands separators, a decimal comma (detected per column), currency signs, percent signs and (123) for negatives. Day/month order of dates like 03/04/2026 is detected per column; when the data never disambiguates it, day-first is assumed and stated.\n- For bar, stacked, pie, line and area charts, rows with the same X value are combined with the chosen aggregation (automatic = sum). With a group column, the first Y column is split into one series per group value (at most 8; the rest become \"Other\"). Top N keeps the categories with the largest totals.\n- Charts are drawn by the site’s own SVG library: colour-blind-safe Okabe–Ito colours plus dash patterns or marker shapes, a text alternative, and the data table below. PNG images are rendered from the same SVG at 2× resolution with ImageMagick.\n- Very large inputs are reduced for drawing only: lines with more than 2,000 points show bucket averages, scatter plots with more than 5,000 points show every n-th point; the table and CSV keep all values.\n\nCheck that the detected column types and the aggregation match your data before publishing a chart.",
        "tags": [
          "charts"
        ],
        "x-mcp-tool": "csv_excel_chart_studio",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CsvExcelChartStudioInput"
              },
              "examples": {
                "example1": {
                  "summary": "Revenue by month, stacked by region",
                  "value": {
                    "data": "Month,Region,Revenue,Orders\n2026-01,North,12400,310\n2026-01,South,9800,250\n2026-02,North,13900,342\n2026-02,South,10150,262\n2026-03,North,15100,371\n2026-03,South,11800,290\n2026-04,North,14650,355\n2026-04,South,12900,301",
                    "chartType": "stacked",
                    "x": "Month",
                    "y": "Revenue",
                    "group": "Region",
                    "png": false
                  }
                },
                "example2": {
                  "summary": "Monthly orders as a line (repeated months summed)",
                  "value": {
                    "data": "Month,Region,Revenue,Orders\n2026-01,North,12400,310\n2026-01,South,9800,250\n2026-02,North,13900,342\n2026-02,South,10150,262\n2026-03,North,15100,371\n2026-03,South,11800,290\n2026-04,North,14650,355\n2026-04,South,12900,301",
                    "chartType": "line",
                    "x": "Month",
                    "y": "Orders",
                    "png": true
                  }
                },
                "example3": {
                  "summary": "Share of revenue by region (pie)",
                  "value": {
                    "data": "Month,Region,Revenue,Orders\n2026-01,North,12400,310\n2026-01,South,9800,250\n2026-02,North,13900,342\n2026-02,South,10150,262\n2026-03,North,15100,371\n2026-03,South,11800,290\n2026-04,North,14650,355\n2026-04,South,12900,301",
                    "chartType": "pie",
                    "x": "Region",
                    "y": "Revenue",
                    "png": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CsvExcelChartStudioResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "CsvExcelChartStudioInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "file": {
            "title": "CSV, TSV or Excel file",
            "description": "CSV/TSV/TXT or .xlsx, max 20 MB. The format is detected from the content. Old .xls files: save as .xlsx first. Upload as {filename, contentType?, contentBase64}. Max 20480 KiB. Accepts .csv,.tsv,.txt,.xlsx,text/csv,text/tab-separated-values,text/plain,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "data": {
            "title": "Or paste data",
            "description": "Comma-, semicolon-, tab- or pipe-separated, first row = headers. Used when no file is uploaded.",
            "type": "string",
            "maxLength": 2000000
          },
          "sheet": {
            "title": "Excel sheet",
            "description": "Sheet name or number; default: the first sheet.",
            "type": "string",
            "maxLength": 120
          },
          "hasHeader": {
            "title": "First row contains column names",
            "type": "boolean",
            "default": true
          },
          "chartType": {
            "title": "Chart type",
            "type": "string",
            "enum": [
              "auto",
              "line",
              "area",
              "bar",
              "stacked",
              "scatter",
              "pie",
              "donut",
              "histogram"
            ],
            "default": "auto"
          },
          "x": {
            "title": "X column (categories or dates)",
            "description": "Column name, letter (A, B …) or number. Empty: first date or text column.",
            "type": "string",
            "maxLength": 200
          },
          "y": {
            "title": "Y columns (values)",
            "description": "One or more column names, comma-separated. Empty: the numeric columns. No numeric column: rows are counted.",
            "type": "string",
            "maxLength": 1000
          },
          "group": {
            "title": "Group / series column",
            "description": "Optional: split the first Y column into one series per value of this column (e.g. Region) – ideal for stacked bars.",
            "type": "string",
            "maxLength": 200
          },
          "aggregation": {
            "title": "Combine repeated X values",
            "type": "string",
            "enum": [
              "auto",
              "sum",
              "avg",
              "count",
              "min",
              "max",
              "median",
              "none"
            ],
            "default": "auto"
          },
          "sort": {
            "title": "Sort",
            "type": "string",
            "enum": [
              "auto",
              "none",
              "x",
              "value-desc",
              "value-asc"
            ],
            "default": "auto"
          },
          "topN": {
            "title": "Top N categories",
            "description": "0 = all (very long category lists are cut automatically).",
            "type": "integer",
            "minimum": 0,
            "maximum": 200,
            "default": 0
          },
          "otherBucket": {
            "title": "Combine the rest into \"Other\"",
            "type": "boolean",
            "default": true
          },
          "bins": {
            "title": "Histogram bins",
            "description": "0 = automatic (Sturges’ rule).",
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "default": 0
          },
          "title": {
            "title": "Chart title",
            "type": "string",
            "maxLength": 140
          },
          "png": {
            "title": "Also create a PNG image",
            "type": "boolean",
            "default": true
          }
        },
        "required": []
      },
      "CsvExcelChartStudioResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "source",
              "columns",
              "chart",
              "table",
              "svg",
              "png"
            ],
            "properties": {
              "source": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "format",
                  "rows",
                  "columns",
                  "sheet",
                  "truncated"
                ],
                "properties": {
                  "format": {
                    "type": "string"
                  },
                  "rows": {
                    "type": "integer"
                  },
                  "columns": {
                    "type": "integer"
                  },
                  "sheet": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "sheets": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "delimiter": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "truncated": {
                    "type": "boolean"
                  }
                }
              },
              "columns": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "type",
                    "nonEmpty",
                    "distinct"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "number",
                        "date",
                        "category",
                        "empty"
                      ]
                    },
                    "nonEmpty": {
                      "type": "integer"
                    },
                    "distinct": {
                      "type": "integer"
                    }
                  }
                }
              },
              "chart": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "type",
                  "title",
                  "x",
                  "y",
                  "group",
                  "aggregation",
                  "sort",
                  "topN",
                  "categories",
                  "series",
                  "points"
                ],
                "properties": {
                  "type": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  },
                  "x": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "y": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "group": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "aggregation": {
                    "type": "string"
                  },
                  "sort": {
                    "type": "string"
                  },
                  "topN": {
                    "type": "integer"
                  },
                  "categories": {
                    "type": "integer"
                  },
                  "series": {
                    "type": "integer"
                  },
                  "points": {
                    "type": "integer"
                  }
                }
              },
              "table": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "header",
                  "rows",
                  "totalRows"
                ],
                "properties": {
                  "header": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "rows": {
                    "type": "array",
                    "items": {
                      "type": "array"
                    }
                  },
                  "totalRows": {
                    "type": "integer"
                  }
                }
              },
              "svg": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "artifactId",
                  "filename",
                  "mime",
                  "bytes",
                  "sha256",
                  "path"
                ],
                "properties": {
                  "artifactId": {
                    "type": "string"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "mime": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer"
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "path": {
                    "type": "string",
                    "description": "Download path on the same site (valid for about 2 hours)."
                  }
                }
              },
              "png": {
                "anyOf": [
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}