{"openapi":"3.0.3","info":{"title":"Wohnungssuche – Speicher-API (d-solve.de)","version":"1.0.0","description":"Speichert eine Seite des Werkzeugs „Wohnungssuche“ auf dem Server und liefert einen kurzen Link. Ohne Konto: Anlegen gibt einen Bearbeitungsschlüssel zurück, der jede spätere Änderung erlaubt. Die Daten sind genau die Link-Parameter des Werkzeugs (siehe Doku). Harte Grenzen: 1000 Seiten insgesamt, 20 Fotos je Seite, 2500000 Bytes je Foto, Aufbewahrung höchstens 90 Tage, dann automatische Löschung. Globale Tageskontingente (Kostenbremse): 300 neue Seiten, 1000 Uploads, 20000 Änderungen, 300000 Bildabrufe je UTC-Tag; danach 503 mit code \"daily-cap\". Verbrauch heute: GET /limits → today."},"externalDocs":{"description":"llms.txt: how the tool works, every parameter of data, the rules for agents, API and MCP","url":"https://d-solve.de/projects/apartment-search/llms.txt"},"x-mcp":{"url":"https://d-solve.de/apartment-search/mcp","transport":"streamable-http","description":"MCP server with one tool per endpoint below (apartment_limits, _create, _get, _update, _delete, _add_image, _delete_image, _rotate_key). Stateless, no login; the edit key is a tool argument."},"servers":[{"url":"https://d-solve.de/apartment-search/api"}],"tags":[{"name":"sites"},{"name":"images"},{"name":"accounts"},{"name":"billing"},{"name":"meta"}],"paths":{"/limits":{"get":{"tags":["meta"],"summary":"Grenzen, Aufbewahrungsoptionen, Funktionen, Login-Anbieter","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/sites":{"post":{"tags":["sites"],"summary":"Seite anlegen (ohne Anmeldung möglich)","description":"Mit Bearer-Session gehört die Seite dem Konto. Antwort enthält den Bearbeitungsschlüssel – genau einmal.","security":[{},{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Data"},"retentionDays":{"type":"integer","enum":[7,30,90],"default":30}}},"example":{"data":{"langs":"de","loc":"Mainz","headline":"Wir suchen eine 3-Zimmer-Wohnung","email":"mail@example.com","phone":"-"},"retentionDays":30}}}},"responses":{"201":{"description":"Angelegt","content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"id":{"type":"string","example":"k7m2p9q4r6t8"},"url":{"type":"string","example":"https://d-solve.de/apartment-search/k7m2p9q4r6t8"},"subpages":{"type":"object","additionalProperties":{"type":"string"}},"data":{"$ref":"#/components/schemas/Data"},"images":{"type":"array","items":{"$ref":"#/components/schemas/Image"}},"imageCount":{"type":"integer"},"retentionDays":{"type":"integer"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"expiresAt":{"type":"integer","description":"Unix-Sekunden. Danach wird die Seite samt Fotos gelöscht."},"owned":{"type":"boolean"}}},{"type":"object","properties":{"editKey":{"type":"string","description":"Nur in dieser Antwort. Wird gehasht gespeichert und kann nicht erneut abgerufen werden."},"apiUrl":{"type":"string"}}}]}}}},"400":{"description":"Ungültige Daten","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Zu groß","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Tageslimit je Absender","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Speicher voll","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/bulk":{"post":{"tags":["sites"],"summary":"Mehrere Seiten anlegen (Premium)","security":[{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"retentionDays":{"type":"integer"},"items":{"type":"array","maxItems":50,"items":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Data"},"retentionDays":{"type":"integer"}}}}}}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"allOf":[{"type":"object","properties":{"id":{"type":"string","example":"k7m2p9q4r6t8"},"url":{"type":"string","example":"https://d-solve.de/apartment-search/k7m2p9q4r6t8"},"subpages":{"type":"object","additionalProperties":{"type":"string"}},"data":{"$ref":"#/components/schemas/Data"},"images":{"type":"array","items":{"$ref":"#/components/schemas/Image"}},"imageCount":{"type":"integer"},"retentionDays":{"type":"integer"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"expiresAt":{"type":"integer","description":"Unix-Sekunden. Danach wird die Seite samt Fotos gelöscht."},"owned":{"type":"boolean"}}},{"type":"object","properties":{"editKey":{"type":"string","description":"Nur in dieser Antwort. Wird gehasht gespeichert und kann nicht erneut abgerufen werden."},"apiUrl":{"type":"string"}}}]}}}}}}},"402":{"description":"Premium nötig","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["sites"],"summary":"Seite lesen (öffentlich, wie der Link selbst)","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"k7m2p9q4r6t8"},"url":{"type":"string","example":"https://d-solve.de/apartment-search/k7m2p9q4r6t8"},"subpages":{"type":"object","additionalProperties":{"type":"string"}},"data":{"$ref":"#/components/schemas/Data"},"images":{"type":"array","items":{"$ref":"#/components/schemas/Image"}},"imageCount":{"type":"integer"},"retentionDays":{"type":"integer"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"expiresAt":{"type":"integer","description":"Unix-Sekunden. Danach wird die Seite samt Fotos gelöscht."},"owned":{"type":"boolean"}}}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Abgelaufen","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["sites"],"summary":"Daten und/oder Aufbewahrung ändern","security":[{"editKey":[]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Data"},"retentionDays":{"type":"integer","description":"Setzt die Frist neu ab jetzt."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"k7m2p9q4r6t8"},"url":{"type":"string","example":"https://d-solve.de/apartment-search/k7m2p9q4r6t8"},"subpages":{"type":"object","additionalProperties":{"type":"string"}},"data":{"$ref":"#/components/schemas/Data"},"images":{"type":"array","items":{"$ref":"#/components/schemas/Image"}},"imageCount":{"type":"integer"},"retentionDays":{"type":"integer"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"expiresAt":{"type":"integer","description":"Unix-Sekunden. Danach wird die Seite samt Fotos gelöscht."},"owned":{"type":"boolean"}}}}}},"401":{"description":"Schlüssel fehlt","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Schlüssel falsch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["sites"],"summary":"Seite samt Fotos löschen","security":[{"editKey":[]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/sites/{id}/verify":{"post":{"tags":["sites"],"summary":"Schlüssel prüfen","security":[{"editKey":[]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"via":{"type":"string","enum":["key","owner"]}}}}}},"403":{"description":"Falsch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{id}/rotate-key":{"post":{"tags":["sites"],"summary":"Neuen Bearbeitungsschlüssel erzeugen (alter wird ungültig)","security":[{"editKey":[]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"editKey":{"type":"string"}}}}}}}}},"/sites/{id}/claim":{"post":{"tags":["accounts"],"summary":"Vorhandene Seite dem angemeldeten Konto zuordnen","security":[{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["editKey"],"properties":{"editKey":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"k7m2p9q4r6t8"},"url":{"type":"string","example":"https://d-solve.de/apartment-search/k7m2p9q4r6t8"},"subpages":{"type":"object","additionalProperties":{"type":"string"}},"data":{"$ref":"#/components/schemas/Data"},"images":{"type":"array","items":{"$ref":"#/components/schemas/Image"}},"imageCount":{"type":"integer"},"retentionDays":{"type":"integer"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"expiresAt":{"type":"integer","description":"Unix-Sekunden. Danach wird die Seite samt Fotos gelöscht."},"owned":{"type":"boolean"}}}}}}}}},"/sites/{id}/images":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["images"],"summary":"Fotos der Seite","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Image"}}}}}}}}},"post":{"tags":["images"],"summary":"Foto hochladen","description":"Drei Wege: Rohdaten mit Content-Type image/*; multipart/form-data mit Feld „file“; oder JSON { \"url\": \"https://…\" } – dann lädt der Server das Bild selbst (für KI-Agenten). Erlaubt: JPEG, PNG, WebP, GIF, AVIF bis 2500000 Bytes, höchstens 20 je Seite. Die zurückgegebene url ist der Wert für photo / p1photo usw.","security":[{"editKey":[]},{"session":[]}],"requestBody":{"content":{"image/*":{"schema":{"type":"string","format":"binary"}},"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}},"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"}}}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image"}}}},"409":{"description":"Fotolimit erreicht","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Zu groß","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Kein unterstütztes Bild","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{id}/images/{imageId}":{"delete":{"tags":["images"],"summary":"Foto löschen","security":[{"editKey":[]},{"session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"imageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/auth/providers":{"get":{"tags":["accounts"],"summary":"Konfigurierte Social-Login-Anbieter","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/auth/login":{"get":{"tags":["accounts"],"summary":"Login starten (302 zum Anbieter)","parameters":[{"name":"provider","in":"query","required":true,"schema":{"type":"string","enum":["google"]}},{"name":"return","in":"query","required":true,"schema":{"type":"string"},"description":"Rücksprung in die App; nur erlaubte Ursprünge. Danach ist das Session-Cookie gesetzt und die App erhält #/auth/ok."}],"responses":{"302":{"description":"Weiterleitung"}}}},"/auth/me":{"get":{"tags":["accounts"],"summary":"Angemeldeter Nutzer mit Premium-Status und Kontolimits","security":[{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Nicht angemeldet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/me/sites":{"get":{"tags":["accounts"],"summary":"Eigene Seiten","security":[{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/billing/checkout":{"post":{"tags":["billing"],"summary":"Stripe-Checkout für Premium starten","security":[{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["return"],"properties":{"return":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"}}}}}}}}},"/billing/portal":{"post":{"tags":["billing"],"summary":"Stripe-Kundenportal (Abo kündigen, Zahlungsdaten)","security":[{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["return"],"properties":{"return":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"}}}}}}}}},"/auth/logout":{"post":{"tags":["accounts"],"summary":"Abmelden","security":[{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/auth/logout-all":{"post":{"tags":["accounts"],"summary":"Überall abmelden","security":[{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/billing/webhook":{"post":{"tags":["billing"],"summary":"Stripe-Webhook (nur für Stripe)","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"securitySchemes":{"editKey":{"type":"http","scheme":"bearer","description":"Bearbeitungsschlüssel aus der Antwort von POST /sites (beginnt mit as_)."},"session":{"type":"apiKey","in":"cookie","name":"__Secure-as_session","description":"HttpOnly-Session-Cookie nach dem Google-Login (GET /auth/login?provider=google&return=…). Nur für Browser auf erlaubten Ursprüngen; schreibende Aufrufe brauchen einen passenden Origin-Header. KI-Agenten nutzen den Bearbeitungsschlüssel."}},"schemas":{"Data":{"type":"object","description":"Die Link-Parameter des Werkzeugs: Parametername → Text, z. B. { \"headline.de\": \"…\", \"email\": \"…\" }. Höchstens 500 Einträge, 10000 Zeichen je Wert, 65536 Bytes insgesamt. Keine data:-Adressen – Bilder hochladen.","additionalProperties":{"type":"string"}},"Image":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"contentType":{"type":"string"},"size":{"type":"integer"},"createdAt":{"type":"integer"}}},"Error":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}}}}}}