{
  "openapi": "3.1.0",
  "info": {
    "title": "Soft Dev Oy — public API",
    "version": "1.0.0",
    "summary": "Read-only facts about the company and its blog.",
    "description": "Static JSON, rebuilt with the site from the same data the pages are rendered from. Read-only: GET only, no authentication, no rate limit, CORS open to every origin. Text that exists in two languages is an object keyed by language, { fi, en }. Dates are YYYY-MM-DD.",
    "contact": {
      "name": "Soft Dev Oy",
      "email": "support@softdev.fi",
      "url": "https://softdev.fi/en/contact"
    }
  },
  "servers": [
    {
      "url": "https://softdev.fi/api/v1"
    }
  ],
  "paths": {
    "/company.json": {
      "get": {
        "summary": "The company: registered details, the key sentence, identifiers.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Company"
                }
              }
            }
          }
        }
      }
    },
    "/posts.json": {
      "get": {
        "summary": "Every published article, newest first, in both languages, without the bodies.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostList"
                }
              }
            }
          }
        }
      }
    },
    "/posts/{id}.json": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "description": "Article id, shared by its two language versions."
          }
        }
      ],
      "get": {
        "summary": "One article in full: fields and the markdown body, in both languages.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Post"
                }
              }
            }
          },
          "404": {
            "description": "No published article has this id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/sections.json": {
      "get": {
        "summary": "Blog sections that have at least one published article, with their descriptions and article counts.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SectionList"
                }
              }
            }
          }
        }
      }
    },
    "/glossary.json": {
      "get": {
        "summary": "The terms defined on the glossary page.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Glossary"
                }
              }
            }
          }
        }
      }
    },
    "/faq.json": {
      "get": {
        "summary": "The questions answered on the FAQ page.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Faq"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "summary": "This document.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "Company": {
        "type": "object",
        "required": [
          "name",
          "legal_name",
          "url",
          "description",
          "business_id",
          "vat_id",
          "euid",
          "founded",
          "address",
          "phone",
          "email",
          "e_invoice",
          "same_as",
          "identifier",
          "platform"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "legal_name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "description": {
            "type": "object",
            "description": "The key sentence: the company in one line, word for word as on the home page.",
            "required": [
              "fi",
              "en"
            ],
            "properties": {
              "fi": {
                "type": "string"
              },
              "en": {
                "type": "string"
              }
            }
          },
          "business_id": {
            "type": "string",
            "description": "Finnish business ID (Y-tunnus)."
          },
          "vat_id": {
            "type": "string"
          },
          "euid": {
            "type": "string",
            "description": "European Unique Identifier in the interconnected business registers."
          },
          "founded": {
            "type": "string",
            "description": "Year and month, YYYY-MM."
          },
          "address": {
            "type": "object",
            "required": [
              "street",
              "postal_code",
              "city",
              "country_code",
              "country"
            ],
            "properties": {
              "street": {
                "type": "string"
              },
              "postal_code": {
                "type": "string"
              },
              "city": {
                "type": "string"
              },
              "country_code": {
                "type": "string",
                "description": "ISO 3166-1 alpha-2."
              },
              "country": {
                "type": "object",
                "required": [
                  "fi",
                  "en"
                ],
                "properties": {
                  "fi": {
                    "type": "string"
                  },
                  "en": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "phone": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "e_invoice": {
            "type": "object",
            "required": [
              "address",
              "operator_id",
              "operator"
            ],
            "properties": {
              "address": {
                "type": "string"
              },
              "operator_id": {
                "type": "string"
              },
              "operator": {
                "type": "string"
              }
            }
          },
          "same_as": {
            "type": "array",
            "description": "Records about the company kept by someone else.",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "identifier": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "property_id",
                "value"
              ],
              "properties": {
                "property_id": {
                  "type": "string"
                },
                "value": {
                  "type": "string"
                }
              }
            }
          },
          "platform": {
            "type": "object",
            "required": [
              "name",
              "url"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "url": {
                "type": "object",
                "required": [
                  "fi",
                  "en"
                ],
                "properties": {
                  "fi": {
                    "type": "string",
                    "format": "uri"
                  },
                  "en": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        }
      },
      "PostList": {
        "type": "object",
        "required": [
          "posts",
          "authors"
        ],
        "properties": {
          "posts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PostSummary"
            }
          },
          "authors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Author"
            }
          }
        }
      },
      "PostSummary": {
        "type": "object",
        "required": [
          "id",
          "section",
          "pillar",
          "author",
          "published",
          "updated",
          "url",
          "fi",
          "en"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Shared by the two language versions."
          },
          "section": {
            "type": "string",
            "description": "Section id; see /sections.json."
          },
          "pillar": {
            "type": "boolean",
            "description": "True for the main article of its section."
          },
          "author": {
            "type": "string",
            "description": "Author id; see \"authors\" in /posts.json."
          },
          "published": {
            "type": "string",
            "format": "date"
          },
          "updated": {
            "type": "string",
            "description": "The later of the two versions' own dates.",
            "format": "date"
          },
          "url": {
            "type": "string",
            "description": "This article in full, as JSON.",
            "format": "uri"
          },
          "fi": {
            "type": "object",
            "required": [
              "slug",
              "title",
              "headline",
              "description",
              "published",
              "updated",
              "reading_time_minutes",
              "url",
              "markdown_url",
              "image_url",
              "image_alt",
              "thumbnail_url",
              "share_card_url"
            ],
            "properties": {
              "slug": {
                "type": "string",
                "description": "The last segment of the article's address in this language."
              },
              "title": {
                "type": "string",
                "description": "The article's name in the lists and in the browser tab."
              },
              "headline": {
                "type": "string",
                "description": "The heading on the article page; the title where the article has no other."
              },
              "description": {
                "type": "string",
                "description": "One or two sentences; also the meta description."
              },
              "published": {
                "type": "string",
                "format": "date"
              },
              "updated": {
                "type": "string",
                "description": "Equal to \"published\" until the article is revised.",
                "format": "date"
              },
              "reading_time_minutes": {
                "type": "integer",
                "minimum": 1
              },
              "url": {
                "type": "string",
                "description": "The article page.",
                "format": "uri"
              },
              "markdown_url": {
                "type": "string",
                "description": "The same article as plain markdown.",
                "format": "uri"
              },
              "image_url": {
                "type": "string",
                "description": "The article's own image, or its share card where it has none.",
                "format": "uri"
              },
              "image_alt": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "What the article's own image shows; null with the share card."
              },
              "thumbnail_url": {
                "type": "string",
                "description": "The image the lists show, 16:9 where the article has one cut for them.",
                "format": "uri"
              },
              "share_card_url": {
                "type": "string",
                "description": "The share image, 1200×630: the article's own, or the card drawn from its title.",
                "format": "uri"
              }
            }
          },
          "en": {
            "type": "object",
            "required": [
              "slug",
              "title",
              "headline",
              "description",
              "published",
              "updated",
              "reading_time_minutes",
              "url",
              "markdown_url",
              "image_url",
              "image_alt",
              "thumbnail_url",
              "share_card_url"
            ],
            "properties": {
              "slug": {
                "type": "string",
                "description": "The last segment of the article's address in this language."
              },
              "title": {
                "type": "string",
                "description": "The article's name in the lists and in the browser tab."
              },
              "headline": {
                "type": "string",
                "description": "The heading on the article page; the title where the article has no other."
              },
              "description": {
                "type": "string",
                "description": "One or two sentences; also the meta description."
              },
              "published": {
                "type": "string",
                "format": "date"
              },
              "updated": {
                "type": "string",
                "description": "Equal to \"published\" until the article is revised.",
                "format": "date"
              },
              "reading_time_minutes": {
                "type": "integer",
                "minimum": 1
              },
              "url": {
                "type": "string",
                "description": "The article page.",
                "format": "uri"
              },
              "markdown_url": {
                "type": "string",
                "description": "The same article as plain markdown.",
                "format": "uri"
              },
              "image_url": {
                "type": "string",
                "description": "The article's own image, or its share card where it has none.",
                "format": "uri"
              },
              "image_alt": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "What the article's own image shows; null with the share card."
              },
              "thumbnail_url": {
                "type": "string",
                "description": "The image the lists show, 16:9 where the article has one cut for them.",
                "format": "uri"
              },
              "share_card_url": {
                "type": "string",
                "description": "The share image, 1200×630: the article's own, or the card drawn from its title.",
                "format": "uri"
              }
            }
          }
        }
      },
      "Post": {
        "type": "object",
        "required": [
          "id",
          "section",
          "pillar",
          "author",
          "published",
          "updated",
          "url",
          "fi",
          "en"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "section": {
            "type": "string"
          },
          "pillar": {
            "type": "boolean"
          },
          "author": {
            "type": "string"
          },
          "published": {
            "type": "string",
            "format": "date"
          },
          "updated": {
            "type": "string",
            "format": "date"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "fi": {
            "$ref": "#/components/schemas/PostVersion"
          },
          "en": {
            "$ref": "#/components/schemas/PostVersion"
          }
        }
      },
      "PostVersion": {
        "type": "object",
        "required": [
          "slug",
          "title",
          "headline",
          "description",
          "published",
          "updated",
          "reading_time_minutes",
          "url",
          "markdown_url",
          "image_url",
          "image_alt",
          "thumbnail_url",
          "share_card_url",
          "summary",
          "sources",
          "faq",
          "body"
        ],
        "properties": {
          "slug": {
            "type": "string",
            "description": "The last segment of the article's address in this language."
          },
          "title": {
            "type": "string",
            "description": "The article's name in the lists and in the browser tab."
          },
          "headline": {
            "type": "string",
            "description": "The heading on the article page; the title where the article has no other."
          },
          "description": {
            "type": "string",
            "description": "One or two sentences; also the meta description."
          },
          "published": {
            "type": "string",
            "format": "date"
          },
          "updated": {
            "type": "string",
            "description": "Equal to \"published\" until the article is revised.",
            "format": "date"
          },
          "reading_time_minutes": {
            "type": "integer",
            "minimum": 1
          },
          "url": {
            "type": "string",
            "description": "The article page.",
            "format": "uri"
          },
          "markdown_url": {
            "type": "string",
            "description": "The same article as plain markdown.",
            "format": "uri"
          },
          "image_url": {
            "type": "string",
            "description": "The article's own image, or its share card where it has none.",
            "format": "uri"
          },
          "image_alt": {
            "type": [
              "string",
              "null"
            ],
            "description": "What the article's own image shows; null with the share card."
          },
          "thumbnail_url": {
            "type": "string",
            "description": "The image the lists show, 16:9 where the article has one cut for them.",
            "format": "uri"
          },
          "share_card_url": {
            "type": "string",
            "description": "The share image, 1200×630: the article's own, or the card drawn from its title.",
            "format": "uri"
          },
          "summary": {
            "type": [
              "string",
              "null"
            ],
            "description": "The article in a few sentences — the \"In brief\" block."
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "title",
                "url",
                "date"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "date": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date"
                }
              }
            }
          },
          "faq": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "q",
                "a"
              ],
              "properties": {
                "q": {
                  "type": "string"
                },
                "a": {
                  "type": "string"
                }
              }
            }
          },
          "body": {
            "type": "string",
            "description": "The article body, in markdown."
          }
        }
      },
      "Author": {
        "type": "object",
        "required": [
          "id",
          "name",
          "job_title",
          "linkedin"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "job_title": {
            "type": "object",
            "required": [
              "fi",
              "en"
            ],
            "properties": {
              "fi": {
                "type": "string"
              },
              "en": {
                "type": "string"
              }
            }
          },
          "linkedin": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "SectionList": {
        "type": "object",
        "required": [
          "sections"
        ],
        "properties": {
          "sections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Section"
            }
          }
        }
      },
      "Section": {
        "type": "object",
        "required": [
          "id",
          "order",
          "posts",
          "pillar_post",
          "fi",
          "en"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "order": {
            "type": [
              "integer",
              "null"
            ]
          },
          "posts": {
            "type": "integer",
            "description": "Published articles in the section."
          },
          "pillar_post": {
            "type": [
              "string",
              "null"
            ],
            "description": "Id of the section's main article; see /posts.json."
          },
          "fi": {
            "$ref": "#/components/schemas/SectionVersion"
          },
          "en": {
            "$ref": "#/components/schemas/SectionVersion"
          }
        }
      },
      "SectionVersion": {
        "type": "object",
        "required": [
          "slug",
          "name",
          "description",
          "text",
          "url",
          "feed_url"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "description": "What the section is about."
          },
          "text": {
            "type": [
              "string",
              "null"
            ],
            "description": "The paragraph that follows the description on the section page."
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "feed_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Glossary": {
        "type": "object",
        "required": [
          "url",
          "terms"
        ],
        "properties": {
          "url": {
            "type": "object",
            "required": [
              "fi",
              "en"
            ],
            "properties": {
              "fi": {
                "type": "string",
                "format": "uri"
              },
              "en": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "terms": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "fi",
                "en"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Shared by the two language versions."
                },
                "fi": {
                  "$ref": "#/components/schemas/Term"
                },
                "en": {
                  "$ref": "#/components/schemas/Term"
                }
              }
            }
          }
        }
      },
      "Term": {
        "type": "object",
        "required": [
          "term",
          "definition",
          "url"
        ],
        "properties": {
          "term": {
            "type": "string"
          },
          "definition": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "The term on the glossary page; the anchor is the term's slug in that language.",
            "format": "uri"
          }
        }
      },
      "Faq": {
        "type": "object",
        "required": [
          "url",
          "items"
        ],
        "properties": {
          "url": {
            "type": "object",
            "required": [
              "fi",
              "en"
            ],
            "properties": {
              "fi": {
                "type": "string",
                "format": "uri"
              },
              "en": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "fi",
                "en"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Also the anchor on the page."
                },
                "fi": {
                  "$ref": "#/components/schemas/Question"
                },
                "en": {
                  "$ref": "#/components/schemas/Question"
                }
              }
            }
          }
        }
      },
      "Question": {
        "type": "object",
        "required": [
          "question",
          "answer",
          "url"
        ],
        "properties": {
          "question": {
            "type": "string"
          },
          "answer": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        }
      }
    }
  }
}
