> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fynn.eu/llms.txt
> Use this file to discover all available pages before exploring further.

# Öffentliches Angebot abrufen

> Gibt die öffentliche, für den Empfänger bestimmte Ansicht eines Angebots zurück. Der Zugriff erfolgt über den persönlichen Einladungslink, ohne Anmeldung.



## OpenAPI

````yaml assets/openapi-v2-offers.json get /public/offers/{id}
openapi: 3.1.0
info:
  title: Fynn V2 Angebote API
  version: 2026-06
  description: >-
    REST API für Fynn Angebote. Damit legst du Angebote an, veröffentlichst sie
    für deine Empfänger, forderst elektronische Unterschriften an und liest die
    öffentliche Empfängeransicht. Angebote werden in der Regel im Wallet
    erstellt und vom Empfänger in der Offer-View angenommen. Diese API ist für
    Integrationen gedacht, die denselben Ablauf programmatisch abbilden.
    Authentifiziere die Verwaltungs-Endpunkte mit einem API-Token deiner
    Organisation. Die öffentlichen Endpunkte erreichst du über den persönlichen
    Einladungslink ohne Anmeldung.
servers:
  - url: https://coreapi.io
    description: Production
  - url: https://preview.coreapi.io
    description: Sandbox
security:
  - ApiToken: []
tags:
  - name: Offers
    description: Angebote anlegen, veröffentlichen und verwalten.
  - name: Offer templates
    description: Wiederverwendbare Angebotsvorlagen.
  - name: Public offer
    description: Öffentliche Empfängeransicht über den Einladungslink.
paths:
  /public/offers/{id}:
    get:
      tags:
        - Public offer
      summary: Öffentliches Angebot abrufen
      description: >-
        Gibt die öffentliche, für den Empfänger bestimmte Ansicht eines Angebots
        zurück. Der Zugriff erfolgt über den persönlichen Einladungslink, ohne
        Anmeldung.
      operationId: getPublicOffer
      parameters:
        - name: id
          in: path
          description: Offer identifier
          required: true
          deprecated: false
          schema:
            type: string
          style: simple
          explode: false
      responses:
        '200':
          description: Offer resource
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Offer.PublicOffer-OfferPublicRead'
        '404':
          description: Resource not found
      deprecated: false
      security: []
components:
  schemas:
    Offer.PublicOffer-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        name:
          type: string
        id:
          description: >-
            Stabiler ULID des Angebots ((string) Offer::getId()). Zusammen mit

            recipientId bildet es das Composite-Credential `{id}-{recipientId}`,
            mit

            dem die käuferseitigen POST-Endpoints (click-accept,
            signature-session,

            terms-acceptance, invoice-details, signed-upload, po-upload,
            delegate)

            adressiert werden. Ohne dieses Feld baute offer-view die Adresse als

            `undefined-{recipientId}` und der Server verwarf sie mit „Invalid
            ULID"

            (FYNN-3272). Auch auf dem Dokument-Level-/Preview-Pfad gesetzt — nur

            recipientId ist dort null.
          type: string
        number:
          description: >-
            Menschenlesbare Angebotsnummer (Offer::getNumber()) — treibt das
            Eyebrow

            „Angebot ANG-…“ im Buyer-Header.
          type: string
        recipientId:
          description: >-
            Credential des anfragenden Empfängers ((string)
            OfferRecipient::getId()).
          type:
            - string
            - 'null'
        startDate:
          description: >-
            FYNN-3264 — Vertragsbeginn (ISO) für die Detail-Box der Rail
            (Start-Zeile).
          type:
            - string
            - 'null'
        signedAt:
          format: date-time
          example: '2021-01-01T00:00:00+00:00'
          description: >-
            D11 — Zeitpunkt der Signatur/Annahme (Offer::getSignedAt());
            serialisiert

            ISO-8601. Treibt die „Angenommen am …“-Anzeige der Success-Rail.
            Null,

            solange keine Signatur erfasst wurde.
          type:
            - string
            - 'null'
        acceptanceMode:
          description: D9 — offer-level acceptance mode (click | esignature | print).
          default: click
          example: click
          type: string
        status:
          description: >-
            Offer state machine current step (open | signing |
            awaiting_invoice_details | signed | archived).
          default: open
          example: open
          type: string
        isPreview:
          description: >-
            D20 — true nur auf dem Live-Preview-Pfad

            (GET /public/offers/{offerId}/preview): gerendert wird der
            DRAFT-Stand

            ohne Recipient-Kontext; offer-view zeigt das Preview-Banner.
          type: boolean
        validUntil:
          format: date-time
          example: '2021-01-01T00:00:00+00:00'
          description: D7 — offer-expiry timestamp (null if not set); serialises ISO-8601.
          type:
            - string
            - 'null'
        dealType:
          description: >-
            D2 — denormalised deal type (new_business | expansion | renewal |
            one_off).
          default: new_business
          example: new_business
          type: string
        contractValue:
          description: >-
            D6 — read-time recurring contract value, honouring flat_fee
            invariant.
          anyOf:
            - $ref: '#/components/schemas/ContractValue-OfferPublicRead'
            - type: 'null'
        termLabel:
          description: D3 — read-time derived contract-term label, du-Form.
          type:
            - string
            - 'null'
        proposal:
          description: >-
            Berechnetes Proposal-View-Model: Phasen, Posten, Rabatte, Summen
            (Euro).
          anyOf:
            - $ref: '#/components/schemas/ProposalViewModel-OfferPublicRead'
            - type: 'null'
        signers:
          description: Dokument-Level Unterzeichner — treibt die Signatur-Zeilen bzw.
          type: array
          items:
            $ref: '#/components/schemas/OfferSignerView-OfferPublicRead'
        recipient:
          description: |-
            D13 — der anfragende Empfänger selbst: persönliche signingUrl
            (Docuseal-Session) und Terms-Gate-Zustand. Null auf dem
            Dokument-Level-/Preview-Pfad ohne Recipient-Credential.
          anyOf:
            - $ref: '#/components/schemas/OfferRecipientView-OfferPublicRead'
            - type: 'null'
        recipients:
          description: >-
            D13 — Auswahl-Kandidaten für den Zeremonie-Dialog (ohne
            E-Mail-Adressen

            Dritter, ohne Countersigner); `isMe` markiert den aktuellen
            Empfänger.
          type: array
          items:
            $ref: '#/components/schemas/OfferRecipientSummary-OfferPublicRead'
        billingData:
          description: >-
            D12 — Zustand der Rechnungsdaten (Parallel-Track): missing |
            incomplete

            | complete plus Vorname der erfassenden Person für die

            first-writer-wins-Anzeige.
          anyOf:
            - $ref: '#/components/schemas/OfferBillingDataView-OfferPublicRead'
            - type: 'null'
        resolvedVariables:
          description: >-
            Aufgeloeste Platzhalter (name => Wert) fuer den `variable`-Block.
            Daten

            berechnet das Backend (Datumsformate fertig); die Frontends ersetzen
            nur.
          type: object
          additionalProperties:
            type: string
        documentUrl:
          description: >-
            D15 — absolute URL des bestehenden öffentlichen Document-Endpoints

            (`GET /public/offers/{offerId}-{recipientId}/document`, API-Domain
            der

            Organisation) für genau dieses Credential; treibt den

            „PDF herunterladen“-Pfad der Print-Annahme. Ohne Recipient (Preview/

            Dokument-Level) wird das Versions-Credential `sha1(offerId +
            number)`

            verwendet. Null, wenn der Organisation keine API-Domain zugeordnet
            ist.
          type:
            - string
            - 'null'
        signedDocumentUrl:
          description: >-
            B1 FYNN-3243 — absolute URL des versiegelten, vollständig
            unterschriebenen

            Angebots-PDFs (inkl. Abschlusszertifikat). Mappt auf

            {@see \Fynn\Core\Domain\Offer\Model\Offer::getSignedDocument()}
            (Media) und

            ist nur gesetzt, sobald ALLE Unterzeichner unterschrieben haben —
            also ab

            Status `awaiting_invoice_details` (`signed`/`archived`
            eingeschlossen).
          type:
            - string
            - 'null'
        billingRecipient:
          description: >-
            FYNN-3264 — Rechnungsempfänger-Sektion der Success-Rail. ≠ null ⇒

            vorhandene Zusammenfassung + „Anpassen“; null ⇒ CTA
            „vervollständigen“.
          anyOf:
            - $ref: '#/components/schemas/OfferBillingRecipient-OfferPublicRead'
            - type: 'null'
        buyer:
          description: >-
            FYNN-3299 — strukturierte Käuferadresse (Kunde) aus dem
            `parties`-Block,

            autoritativ vom Backend. Quelle für das Vorbefüllen des
            Rechnungsdaten-

            Formulars (Fallback, wenn „Rechnung an" leer/„Wie Kunde" ist). Null,
            wenn

            der Verkäufer keinen Käufer gepflegt hat.
          anyOf:
            - $ref: '#/components/schemas/OfferPartyAddress-OfferPublicRead'
            - type: 'null'
        billing:
          description: >-
            FYNN-3299 — strukturierte Rechnungsadresse (Rechnung an) aus dem

            `parties`-Block. Das Rechnungsdaten-Formular (InvoiceDetailsForm)
            wird IMMER

            hieraus vorbefüllt; ist „Rechnung an" leer/„Wie Kunde", fällt es auf

            {@see self::$buyer} zurück. Trägt `addressId` ≠ null, wenn der
            Verkäufer eine

            unveränderte Bestandsadresse gewählt hat — dann bietet das
            offer-view sie zum

            Bestätigen an, statt das leere Formular zu zeigen.
          anyOf:
            - $ref: '#/components/schemas/OfferPartyAddress-OfferPublicRead'
            - type: 'null'
        billingEmail:
          description: >-
            FYNN-3299 — abgeleitete Rechnungs-E-Mail aus dem `parties`-Block
            (Kontakt der

            Rechnungspartei, sonst des Käufers) zum Vorbefüllen des Formulars.
          type:
            - string
            - 'null'
        poNumber:
          description: >-
            FYNN-3299 — vorbelegte PO-/Bestellnummer aus dem `parties`-Block
            (attrs.poNumber).
          type:
            - string
            - 'null'
        tenantSettings:
          description: |-
            FYNN-3264 — Organisations-Schalter für die Off-Ramps der Buyer-Shell
            (allowReject, printFallbackAlways). Sichere Defaults (beide false).
          anyOf:
            - $ref: '#/components/schemas/OfferTenantSettings-OfferPublicRead'
            - type: 'null'
        termsUrl:
          description: >-
            D13/D22 — Link-Ziele der Terms-Checkbox am Signatur-CTA, aus der

            Tenant-Appearance (conditionsUrl → termsUrl, privacyUrl). Null, wenn
            die

            Organisation keine URL gepflegt hat — das Frontend rendert den
            Begriff

            dann als reinen Text statt als Link.
          type:
            - string
            - 'null'
        privacyUrl:
          type:
            - string
            - 'null'
        logoUrl:
          description: >-
            FYNN-3294 — autoritatives Brand-Logo der Organisation für genau
            dieses

            Angebot (gespeichertes Appearance-Logo des Offer-Vertriebskanals,
            Fallback

            Default-Channel). Anders als der host-aufgelöste
            `/public/sales-channel/config`

            trägt das Angebot seinen Tenant immer mit sich — der öffentliche

            offer-view-Link hat keinen Tenant-Host, weshalb die Config dort das
            Logo nicht

            zuverlässig auflösen kann. offer-view bevorzugt darum dieses Feld
            für Header

            UND Druck/PDF. NIE leer: ohne gepflegtes Logo greift der
            App-Logo-Fallback

            ({@see \Fynn\Core\Domain\Tenant\Model\Appearance::getLogoUrl()} mit
            Fallback),

            damit das Logo „IMMER" erscheint.
          type: string
        contactPerson:
          anyOf:
            - $ref: '#/components/schemas/ContactPerson-OfferPublicRead'
            - type: 'null'
        sections:
          type: array
          items:
            type: string
        showDsrRoom:
          description: >-
            FYNN-3421 — autoritative Entscheidung, ob die käuferseitige Ansicht
            den

            Digital-Sales-Room-Rahmen rendert oder das Angebot direkt zum
            Signieren

            zeigt. true nur, wenn das Angebot tatsächlich DSR-Inhalt trägt
            (mindestens

            eine versteckte/„Nur DSR“-Section mit Inhalt). Ohne DSR-Blöcke false
            — die

            Frontends fallen dann auf die direkte, signierbare Angebots-Ansicht
            zurück

            statt eine leere Raum-Hülle zu zeigen. Die Frontends rendern nur
            dieses

            Flag, sie leiten es nicht selbst ab.
          type: boolean
        offerLineItems:
          type: array
          items:
            type: string
        signed:
          type: boolean
        canSign:
          type: boolean
    ContractValue-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        amountCents:
          type: integer
        currency:
          type: string
        interval:
          description: Interval the price applies to (monthly | quarterly | yearly | once).
          type: string
    ProposalViewModel-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        hasContent:
          description: >-
            Pro-Phase liegen die Zwischensummen je Kadenz
            (ProposalPhase::subtotals).
          type: boolean
        currency:
          description: >-
            Pro-Phase liegen die Zwischensummen je Kadenz
            (ProposalPhase::subtotals).
          type: string
        multiPhase:
          description: >-
            Pro-Phase liegen die Zwischensummen je Kadenz
            (ProposalPhase::subtotals).
          type: boolean
        phases:
          description: >-
            Pro-Phase liegen die Zwischensummen je Kadenz
            (ProposalPhase::subtotals).
          type: array
          items:
            $ref: '#/components/schemas/ProposalPhase-OfferPublicRead'
        oneTime:
          description: >-
            Pro-Phase liegen die Zwischensummen je Kadenz
            (ProposalPhase::subtotals).
          type: array
          items:
            $ref: '#/components/schemas/ProposalLine-OfferPublicRead'
        oneTimeTotal:
          $ref: '#/components/schemas/MoneyView-OfferPublicRead'
          description: >-
            Pro-Phase liegen die Zwischensummen je Kadenz
            (ProposalPhase::subtotals).
        terms:
          description: >-
            Pro-Phase liegen die Zwischensummen je Kadenz
            (ProposalPhase::subtotals).
          type: array
          items:
            $ref: '#/components/schemas/ProposalTerm-OfferPublicRead'
        contractStart:
          description: >-
            Pro-Phase liegen die Zwischensummen je Kadenz
            (ProposalPhase::subtotals).
          type:
            - string
            - 'null'
        contractEnd:
          description: >-
            Pro-Phase liegen die Zwischensummen je Kadenz
            (ProposalPhase::subtotals).
          type:
            - string
            - 'null'
        poNumber:
          description: >-
            Pro-Phase liegen die Zwischensummen je Kadenz
            (ProposalPhase::subtotals).
          type:
            - string
            - 'null'
    OfferSignerView-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        name:
          type: string
        roleLabel:
          type: string
        isCountersigner:
          type: boolean
        firstName:
          type: string
        signingStatus:
          type: string
        isMe:
          type: boolean
    OfferRecipientView-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        id:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
        role:
          type: string
        signingUrl:
          type:
            - string
            - 'null'
        termsAccepted:
          type: boolean
    OfferRecipientSummary-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        id:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        role:
          type: string
        isMe:
          type: boolean
    OfferBillingDataView-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        state:
          type: string
        providedByFirstName:
          type:
            - string
            - 'null'
        costCenter:
          type:
            - string
            - 'null'
        leitwegId:
          type:
            - string
            - 'null'
    OfferBillingRecipient-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        company:
          type:
            - string
            - 'null'
        contactName:
          type:
            - string
            - 'null'
        addressLines:
          type: array
          items:
            type: string
        billingEmail:
          type:
            - string
            - 'null'
        vatId:
          type:
            - string
            - 'null'
    OfferPartyAddress-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        companyName:
          type:
            - string
            - 'null'
        salutation:
          type:
            - string
            - 'null'
        firstName:
          type:
            - string
            - 'null'
        lastName:
          type:
            - string
            - 'null'
        street:
          type: string
        houseNumber:
          type:
            - string
            - 'null'
        zip:
          type: string
        city:
          type: string
        country:
          type: string
        vatId:
          type:
            - string
            - 'null'
        addition:
          type:
            - string
            - 'null'
        addressId:
          type:
            - string
            - 'null'
    OfferTenantSettings-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        allowReject:
          type: boolean
        printFallbackAlways:
          type: boolean
    ContactPerson-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        id:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
        avatar:
          type:
            - string
            - 'null'
        phone:
          type:
            - string
            - 'null'
        linkedin:
          type:
            - string
            - 'null'
        position:
          type:
            - string
            - 'null'
        website:
          type:
            - string
            - 'null'
    ProposalPhase-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        start:
          type:
            - string
            - 'null'
        end:
          type:
            - string
            - 'null'
        periodLabel:
          type:
            - string
            - 'null'
        name:
          type:
            - string
            - 'null'
        lines:
          type: array
          items:
            $ref: '#/components/schemas/ProposalLine-OfferPublicRead'
        subtotals:
          type: array
          items:
            $ref: '#/components/schemas/ProposalCadenceSubtotal-OfferPublicRead'
        tcv:
          anyOf:
            - $ref: '#/components/schemas/MoneyView-OfferPublicRead'
            - type: 'null'
    ProposalLine-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        name:
          type: string
        description:
          type:
            - string
            - 'null'
        quantityLabel:
          type: string
        isFlatFee:
          type: boolean
        isOneTime:
          type: boolean
        unitPrice:
          $ref: '#/components/schemas/MoneyView-OfferPublicRead'
        intervalLabel:
          type: string
        originalAmount:
          $ref: '#/components/schemas/MoneyView-OfferPublicRead'
        amount:
          $ref: '#/components/schemas/MoneyView-OfferPublicRead'
        hasDiscount:
          type: boolean
        discountLabel:
          type:
            - string
            - 'null'
        pricingModel:
          type:
            - string
            - 'null'
        pricingModelLabel:
          type:
            - string
            - 'null'
        pricingModelHint:
          type:
            - string
            - 'null'
        tierPriceLabel:
          type:
            - string
            - 'null'
        hasTierFlatFee:
          type: boolean
        tiers:
          type: array
          items:
            $ref: '#/components/schemas/ProposalTier-OfferPublicRead'
    MoneyView-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        amount:
          type: integer
        precision:
          type: integer
        currencyCode:
          type: string
        formatted:
          type: string
    ProposalTerm-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        contractPeriod:
          type: string
        cancellationPeriod:
          type: string
        contractPeriodLabel:
          type:
            - string
            - 'null'
        cancellationPeriodLabel:
          type:
            - string
            - 'null'
    ProposalCadenceSubtotal-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        label:
          type: string
        amount:
          $ref: '#/components/schemas/MoneyView-OfferPublicRead'
    ProposalTier-OfferPublicRead:
      type: object
      description: ''
      deprecated: false
      properties:
        rangeLabel:
          type: string
        unitPrice:
          $ref: '#/components/schemas/MoneyView-OfferPublicRead'
        flatFee:
          anyOf:
            - $ref: '#/components/schemas/MoneyView-OfferPublicRead'
            - type: 'null'
  securitySchemes:
    ApiToken:
      type: http
      scheme: bearer
      description: >-
        API-Token der Organisation. Sende es als Authorization: Bearer api_...
        Das Token ist fest an genau eine Organisation gebunden.

````