> ## Documentation Index
> Fetch the complete documentation index at: https://paperplane-justin-winter-s-projects.vercel.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Review a delivered order

> One review per order. The reviewer identity (name, city, state) is derived server-side from the order return address — it is never accepted from the caller. Requires the `capability_token` returned by the order creation response: publishing attribution is a public action, so the order id alone is not enough.



## OpenAPI

````yaml /openapi.json post /v1/reviews
openapi: 3.1.0
info:
  title: paperplane API
  version: 1.0.0
  summary: Send real physical mail from code.
  description: >-
    Upload a PDF or paste text; we print it and hand it to USPS the next
    business day. No account required — pay per letter with a Stripe link or a
    prepaid credit code, and use `sandbox: true` to exercise the whole flow for
    free.


    Every failure returns the same envelope: `status`, a stable machine-readable
    `code`, a human `reason`, and a `next` array of concrete recovery steps.


    This document is generated from the same zod schemas the server validates
    with, so it cannot describe an endpoint that does not exist.
  contact:
    name: paperplane support
    url: https://sendpaperplane.com/contact
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary
  termsOfService: https://sendpaperplane.com/terms
servers:
  - url: https://sendpaperplane.com
    description: Production
security: []
tags:
  - name: Mail
    description: Quote, send, track, and cancel letters.
  - name: Credits
    description: Prepaid balances that pay for letters without a card.
  - name: Reviews
    description: Post-delivery feedback. Identity is derived from the order, not supplied.
  - name: Addresses
    description: >-
      Typeahead and reverse geocoding. Convenience only; USPS verification is
      authoritative.
  - name: Meta
    description: Machine-readable description of this API.
paths:
  /v1/reviews:
    post:
      tags:
        - Reviews
      summary: Review a delivered order
      description: >-
        One review per order. The reviewer identity (name, city, state) is
        derived server-side from the order return address — it is never accepted
        from the caller. Requires the `capability_token` returned by the order
        creation response: publishing attribution is a public action, so the
        order id alone is not enough.
      operationId: createReview
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateReview'
            example:
              order_id: ord_1a2b3c4d5e6f7a8b
              stars: 5
              comment: >-
                Sent a certified letter without leaving my desk. Arrived in 3
                days.
              capability_token: ppc_e5f6g7h8
      responses:
        '201':
          description: The recorded review
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReviewResponse'
              example:
                status: ok
                review:
                  id: rev_a1b2c3d4
                  stars: 5
                  comment: >-
                    Sent a certified letter without leaving my desk. Arrived in
                    3 days.
                  name: Jordan R.
                  city: Springfield
                  state: IL
                  category: certified
                  created_at: '2026-08-23T12:00:00.000Z'
        '400':
          description: Malformed body, or `invalid_stars` for a value outside 1-5.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >-
            `invalid_capability` — no `capability_token`, or one issued for a
            different order or action. The review token is the `ppc_`-prefixed
            `capability.review_token` from the order response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: No order with that id.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            `not_reviewable` — that order is not delivered, or has already been
            reviewed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '410':
          description: '`expired_capability` — the review token is past its 7-day window.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    CreateReview:
      type: object
      properties:
        order_id:
          type: string
          minLength: 1
          maxLength: 60
        stars:
          type: number
        comment:
          type: string
          maxLength: 500
        capability_token:
          type: string
      required:
        - order_id
        - stars
    ReviewResponse:
      type: object
      properties:
        status:
          type: string
          const: ok
        review:
          $ref: '#/components/schemas/Review'
      required:
        - status
        - review
    Error:
      type: object
      properties:
        status:
          type: string
          enum:
            - failed
            - action_required
        code:
          type: string
        reason:
          type: string
        next:
          type: array
          items:
            type: string
      required:
        - status
        - code
        - reason
        - next
    Review:
      type: object
      properties:
        id:
          type: string
        stars:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
        comment:
          anyOf:
            - type: string
            - type: 'null'
        name:
          type: string
        city:
          type: string
        state:
          type: string
        category:
          type: string
        sample:
          type: boolean
        created_at:
          type: string
      required:
        - id
        - stars
        - comment
        - name
        - city
        - state
        - category
        - created_at

````