{
  "openapi": "3.1.0",
  "info": {
    "title": "Saightly API",
    "description": "Saightly är en svensk marknadsplats för lokala tjänster från verifierade företag (Bolagsverket). Sök tjänster, hitta lediga tider, boka/avropa och skicka generella offertförfrågningar till flera företag. Byggd för både människor och AI-agenter. Klistra in denna spec som en Action i en ChatGPT Custom GPT (eller motsvarande) för att låta assistenten använda Saightly.",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://saightly.com"
    }
  ],
  "paths": {
    "/api/sok.json": {
      "get": {
        "operationId": "sokTjanster",
        "summary": "Sök lokala tjänster i fritext",
        "description": "Tolkar en naturlig sökfråga (kategori, ort, brådska) och returnerar rankade leverantörer med organisationsnummer, pris och betyg.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Sökfråga i naturligt språk, t.ex. 'snickare i Vara asap'."
          }
        ],
        "responses": {
          "200": {
            "description": "Rankade träffar",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "antal": {
                      "type": "integer"
                    },
                    "traffar": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "slug": {
                            "type": "string"
                          },
                          "rubrik": {
                            "type": "string"
                          },
                          "orgnr": {
                            "type": "string"
                          },
                          "namn": {
                            "type": "string"
                          },
                          "kategori": {
                            "type": "string"
                          },
                          "ort": {
                            "type": "string"
                          },
                          "pris_fran_kr": {
                            "type": "integer"
                          },
                          "betyg": {
                            "type": "number"
                          },
                          "tillganglighet": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/tjanst/{slug}.json": {
      "get": {
        "operationId": "lasTjanst",
        "summary": "Läs en specifik tjänst",
        "description": "Hämtar detaljer för en tjänst via dess slug (från sokTjanster): rubrik, kategori, ort, pris, betyg och leverantörens organisationsnummer.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tjänstens slug, t.ex. 'koksrenovering-vara'."
          }
        ],
        "responses": {
          "200": {
            "description": "Tjänstedetaljer",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "slug": {
                      "type": "string"
                    },
                    "rubrik": {
                      "type": "string"
                    },
                    "kategori": {
                      "type": "string"
                    },
                    "ort": {
                      "type": "string"
                    },
                    "pris_fran_kr": {
                      "type": "integer"
                    },
                    "betyg": {
                      "type": "number"
                    },
                    "tillganglighet": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "foretag": {
                      "type": "object",
                      "properties": {
                        "orgnr": {
                          "type": "string"
                        },
                        "namn": {
                          "type": "string"
                        },
                        "verifierad": {
                          "type": "boolean"
                        },
                        "url": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Okänd slug"
          }
        }
      }
    },
    "/api/foretag/{orgnr}.json": {
      "get": {
        "operationId": "lasForetag",
        "summary": "Läs ett företag",
        "description": "Hämtar grunduppgifter för ett organisationsnummer (namn, status, adress, SNI) från Bolagsverket-datakällan.",
        "parameters": [
          {
            "name": "orgnr",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Organisationsnummer (10 siffror)."
          }
        ],
        "responses": {
          "200": {
            "description": "Företagsuppgifter",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Okänt organisationsnummer"
          }
        }
      }
    },
    "/api/tider.json": {
      "get": {
        "operationId": "ledigaTider",
        "summary": "Nästa lediga tider hos en leverantör",
        "description": "Genererar lediga tider för en tjänst. Använd en tid härifrån som bekraftad_tid i avropaTjanst för direktbokning.",
        "parameters": [
          {
            "name": "orgnr",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Leverantörens organisationsnummer."
          },
          {
            "name": "slug",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Tjänstens slug (från sokTjanster)."
          },
          {
            "name": "antal",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Antal tider att returnera."
          }
        ],
        "responses": {
          "200": {
            "description": "Lediga tider",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orgnr": {
                      "type": "string"
                    },
                    "slots": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "description": "ISO 8601-tid"
                      }
                    },
                    "resurser": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "namn": {
                            "type": "string"
                          },
                          "roll": {
                            "type": "string"
                          },
                          "betyg": {
                            "type": "number"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/avrop.json": {
      "post": {
        "operationId": "avropaTjanst",
        "summary": "Skapa ett avrop (förfrågan eller bokning)",
        "description": "Skapar en förfrågan, eller en bokning med vald tid (bekraftad_tid). Vid bokning KRÄVS kontakt med namn, epost och telefon — annars 400. Leverantören bekräftar och kunden får bekräftelse och kalenderinbjudan via mejl.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "orgnr",
                  "kontakt"
                ],
                "properties": {
                  "orgnr": {
                    "type": "string",
                    "description": "Leverantörens organisationsnummer."
                  },
                  "bekraftad_tid": {
                    "type": "string",
                    "description": "Vald ledig tid (ISO 8601) för direktbokning. Utelämna för en förfrågan."
                  },
                  "resurs_id": {
                    "type": "string",
                    "description": "Vald utförare (valfritt)."
                  },
                  "ordervarde": {
                    "type": "integer",
                    "description": "Ordervärde i kr (valfritt)."
                  },
                  "kontakt": {
                    "type": "object",
                    "properties": {
                      "namn": {
                        "type": "string"
                      },
                      "epost": {
                        "type": "string"
                      },
                      "telefon": {
                        "type": "string"
                      },
                      "meddelande": {
                        "type": "string"
                      }
                    },
                    "description": "Kundens kontaktuppgifter. Vid bokning (bekraftad_tid) krävs namn, epost och telefon."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Avropet skapat",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "typ": {
                      "type": "string"
                    },
                    "avgift_kr": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/forfragan.json": {
      "post": {
        "operationId": "skapaOffertforfragan",
        "summary": "Generell offertförfrågan till flera företag",
        "description": "Skickar en offertförfrågan — för jobb i alla storlekar — till flera verifierade företag i en bransch. AI strukturerar briefen; matchande företag återkommer med varsin offert som kunden jämför och väljer.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "profil",
                  "beskrivning",
                  "kontakt"
                ],
                "properties": {
                  "profil": {
                    "type": "string",
                    "enum": [
                      "bygg",
                      "stad",
                      "it",
                      "konsult",
                      "transport",
                      "gront",
                      "kreativt",
                      "vard",
                      "generisk"
                    ],
                    "description": "Bransch för jobbet."
                  },
                  "beskrivning": {
                    "type": "string",
                    "description": "Jobbet i naturligt språk (minst 15 tecken)."
                  },
                  "ort": {
                    "type": "string",
                    "description": "Ort där jobbet ska utföras (styr geografisk matchning)."
                  },
                  "kontakt": {
                    "type": "object",
                    "required": [
                      "epost"
                    ],
                    "properties": {
                      "namn": {
                        "type": "string"
                      },
                      "epost": {
                        "type": "string",
                        "description": "Dit offertsvaren skickas."
                      },
                      "telefon": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Förfrågan skapad och utskickad",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "token": {
                      "type": "string"
                    },
                    "mottagare": {
                      "type": "string"
                    },
                    "notifierade": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/forfragan-status.json": {
      "get": {
        "operationId": "lasOffertforfragan",
        "summary": "Läs status och inkomna offerter för en offertförfrågan",
        "description": "Returnerar förfrågans status och alla inkomna offerter (företag, verifiering, betyg, summa, pristyp: fastpris = bindande, budget = riktpris). token är kundens hemlighet från skapaOffertforfragan. Använd valjOffert för att välja vinnare.",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Förfrågningstoken (från skapaOffertforfragan-svaret)."
          }
        ],
        "responses": {
          "200": {
            "description": "Status + offerter",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status_forfragan": {
                      "type": "string",
                      "enum": [
                        "ny",
                        "utskickad",
                        "stangd"
                      ]
                    },
                    "antal_offerter": {
                      "type": "integer"
                    },
                    "offerter": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "foretag": {
                            "type": "string"
                          },
                          "verifierad": {
                            "type": "boolean"
                          },
                          "betyg": {
                            "type": "number",
                            "nullable": true
                          },
                          "summa_kr": {
                            "type": "integer"
                          },
                          "pristyp": {
                            "type": "string",
                            "enum": [
                              "fastpris",
                              "budget"
                            ]
                          },
                          "meddelande": {
                            "type": "string",
                            "nullable": true
                          },
                          "vald": {
                            "type": "boolean"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/forfragan-val.json": {
      "post": {
        "operationId": "valjOffert",
        "summary": "Välj vinnande offert på en offertförfrågan",
        "description": "Vald offert accepteras (företaget får kundens kontaktuppgifter), övriga avböjs vänligt och förfrågan stängs. Idempotent.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token",
                  "offert_id"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "description": "Förfrågningstoken."
                  },
                  "offert_id": {
                    "type": "string",
                    "description": "Offertens id från lasOffertforfragan."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vald",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "vald": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
