openapi: 3.1.0
info:
  title: Forman3D Letters Paid Mailing API
  version: 0.1.0
  description: >
    Public paid-mailing handoff API for Forman3D Letters. Use this to save a
    single paid mailing request and receive a Stripe Checkout URL tied to that
    saved local Forman3D order. Current scope is mailing to U.S. recipient
    addresses only; the sender/customer may be outside the U.S.
    Paid requests pass Forman3D's protective review gate before normal checkout
    is created. If a draft is blocked or needs owner judgment, the API returns a
    manual_review_available response instead of a checkout URL. Manual-review
    checkout requires a second explicit create_manual_review_pending action.
    Base first-class mailing is $10. Certified Mail is available as a $9 add-on.
    Certified proof comes back to Forman3D, and Forman3D emails the customer
    when the USPS receipt or confirmation is received.
servers:
  - url: https://www.forman3d.com
    description: Production site
components:
  schemas:
    PaidLetterRequest:
      type: object
      additionalProperties: false
      required:
        - letterType
        - lettersName
        - senderAddress
        - lettersEmail
        - recipientName
        - recipientAddress
        - letterDetails
      properties:
        letterType:
          type: string
          enum:
            - send-my-letter
            - property-or-access-request
            - demand-for-payment
            - demand-for-completion
            - hoa-violation-notice
            - pay-or-quit-notice
            - membership-cancellation-notice
            - letter-of-recommendation
            - massachusetts-93a-demand
            - new-hampshire-security-deposit-demand
            - connecticut-security-deposit-demand
            - rhode-island-security-deposit-demand
            - maine-security-deposit-demand
            - vermont-security-deposit-demand
            - other-standard-letter
          example: property-or-access-request
        lettersName:
          type: string
          description: Sender full name.
          example: Alex Sender
        senderAddress:
          type: string
          description: Sender mailing/return address as printable multiline text. The sender/customer may be outside the U.S.
          example: |
            123 Example St
            Exampletown, NH 03031
        lettersEmail:
          type: string
          format: email
          description: Sender email address.
          example: alex.sender@example.com
        lettersPhone:
          type: string
          description: Optional sender phone number.
          example: "15550102468"
        recipientName:
          type: string
          description: Recipient full name.
          example: Jane Smith
        recipientAddress:
          type: string
          description: Recipient mailing address as printable multiline text. Must be a U.S. mailing address.
          example: |
            456 Oak St
            Nashua, NH 03031
        mailService:
          type: string
          enum:
            - first-class
            - certified
          default: first-class
          description: Choose first-class for the $10 base service or certified for Certified Mail at $19 total.
          example: certified
        letterDetails:
          type: string
          description: Full body of the letter to be mailed.
          example: |
            Dear Jane Smith,

            I am writing regarding a tree on your property that appears to be leaning over my fence.
    CreatePendingRequest:
      type: object
      additionalProperties: false
      required:
        - action
        - pageUrl
        - letterRequest
      properties:
        action:
          type: string
          enum:
            - create_pending
            - create_manual_review_pending
          example: create_pending
          description: Use create_pending for normal checkout. If the response status is manual_review_available and the user explicitly chooses paid manual review, call create_manual_review_pending.
        requestId:
          type: string
          description: Optional caller-supplied request identifier.
          example: F3D-LT-260318-170100-abc123
        pageUrl:
          type: string
          description: Source page or app route creating the request.
          example: /letters/agent/
        letterRequest:
          $ref: '#/components/schemas/PaidLetterRequest'
    Summary:
      type: object
      additionalProperties: false
      properties:
        letterType:
          type: string
          example: property-or-access-request
        senderName:
          type: string
          example: Alex Sender
        recipientName:
          type: string
          example: Jane Smith
        mailService:
          type: string
          example: certified
        totalAmountCents:
          type: integer
          example: 1900
        paymentState:
          type: string
          example: pending_checkout
    CreatePendingResponse:
      type: object
      additionalProperties: false
      required:
        - ok
        - message
        - data
      properties:
        ok:
          type: boolean
          example: true
        message:
          type: string
          example: Pending paid mailing saved.
        data:
          type: object
          additionalProperties: false
          required:
            - requestId
            - summary
            - checkoutUrl
            - status
          properties:
            requestId:
              type: string
              example: F3D-LT-260318-170100-abc123
            summary:
              $ref: '#/components/schemas/Summary'
            checkoutUrl:
              type: string
              format: uri
              description: Stripe Checkout URL returned by Stripe for the saved Forman3D order.
              example: https://checkout.stripe.com/c/pay/cs_live_example
            orderNumber:
              type: string
              description: Forman3D internal order number for the paid mailing request.
              example: LT-000123
            status:
              type: string
              example: pending_checkout
            stripeMode:
              type: string
              example: live
            manualReviewRequested:
              type: boolean
              example: false
    ManualReviewAvailableResponse:
      type: object
      additionalProperties: false
      required:
        - ok
        - message
        - data
      properties:
        ok:
          type: boolean
          example: true
        message:
          type: string
          example: This draft needs review before we can mail it.
        data:
          type: object
          additionalProperties: false
          required:
            - requestId
            - status
            - safetyStatus
            - manualReviewAvailable
          properties:
            requestId:
              type: string
              example: F3D-LT-260318-170100-abc123
            status:
              type: string
              enum:
                - manual_review_available
            safetyStatus:
              type: string
              enum:
                - blocked
                - needs_owner_review
              example: needs_owner_review
            manualReviewAvailable:
              type: boolean
              example: true
            message:
              type: string
              example: This draft needs review before we can mail it. You can revise the letter and check again, or request manual review.
            reviewItems:
              type: array
              items:
                type: object
    ErrorResponse:
      type: object
      additionalProperties: false
      required:
        - ok
        - message
      properties:
        ok:
          type: boolean
          example: false
        message:
          type: string
          example: Missing required paid mailing fields.
        data:
          type:
            - object
            - "null"
          nullable: true
paths:
  /api/letters-paid.php:
    post:
      summary: Save a paid mailing request and get the checkout URL
      operationId: createPaidMailingRequest
      description: >
        Saves one Forman3D paid-letter request, returns a request ID, and
        returns the Stripe Checkout URL the user should open to complete
        payment. Recipient mailing address must be in the United States; the
        sender/customer may be outside the U.S. Set
        `letterRequest.mailService` to `certified` when the user chooses the
        Certified Mail add-on. This endpoint does not provide the assistive
        mail-readiness review. It runs the protective gate only. If normal
        checkout is blocked or uncertain, the response can be
        `manual_review_available`; only call `create_manual_review_pending`
        after the user explicitly chooses paid manual review.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePendingRequest'
      responses:
        '200':
          description: Paid mailing request saved, or manual review offered before checkout.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/CreatePendingResponse'
                  - $ref: '#/components/schemas/ManualReviewAvailableResponse'
        '400':
          description: Invalid or incomplete request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '405':
          description: Method not allowed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
