{
  "openapi": "3.1.0",
  "info": {
    "title": "Pepper audit quotes",
    "version": "1.0.0",
    "description": "Quote creation only. No authentication required. Ask the user for missing answers and permission to request a proposal; creation saves their contact details and requests emails to the contact and Pepper. Return the private link for the customer to review and accept on the website."
  },
  "servers": [
    {
      "url": "https://www.pepperauditors.com"
    }
  ],
  "security": [],
  "externalDocs": {
    "url": "https://www.pepperauditors.com/agents"
  },
  "paths": {
    "/api/quote": {
      "post": {
        "operationId": "create_proposal",
        "summary": "Create an audit proposal",
        "description": "Generate and privately retain 32 cryptographically random bytes as a 64-character lowercase hex idempotency_key. Retry identical details with the same key after a lost response. Never log the key or put it in a URL. Preserve the user’s partner ref as ref_code and promo code as promo_code. Individual plans require address, city, state, zip and participant_count. Pooled plans require plan_sponsor and adopter counts that add up. Price is authoritative only from the saved response; no acceptance or engagement delivery occurs.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "plan_type": {
                    "type": "string",
                    "enum": [
                      "individual",
                      "pep"
                    ]
                  },
                  "company_name": {
                    "type": "string",
                    "description": "The employer or pooled plan business, not the recordkeeper.",
                    "maxLength": 500
                  },
                  "plan_name": {
                    "type": "string",
                    "description": "The actual retirement plan name.",
                    "maxLength": 500
                  },
                  "plan_sponsor": {
                    "type": "string",
                    "description": "Pooled plan sponsor; required for PEP.",
                    "maxLength": 500
                  },
                  "contact_name": {
                    "type": "string",
                    "description": "Person requesting the proposal.",
                    "maxLength": 500
                  },
                  "contact_email": {
                    "type": "string",
                    "description": "Email for the proposal.",
                    "maxLength": 500
                  },
                  "contact_phone": {
                    "type": "string",
                    "description": "Optional phone.",
                    "maxLength": 500
                  },
                  "address": {
                    "type": "string",
                    "description": "Street address; required for individual plans.",
                    "maxLength": 500
                  },
                  "city": {
                    "type": "string",
                    "description": "City; required for individual plans.",
                    "maxLength": 500
                  },
                  "state": {
                    "type": "string",
                    "description": "Two-letter US state; required.",
                    "maxLength": 500
                  },
                  "zip": {
                    "type": "string",
                    "description": "ZIP code; required for individual plans.",
                    "maxLength": 500
                  },
                  "ein": {
                    "type": "string",
                    "description": "Optional EIN as XX-XXXXXXX.",
                    "maxLength": 500
                  },
                  "participant_count": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000000,
                    "description": "Participants; required for individual plans."
                  },
                  "adopter_count": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000000,
                    "description": "Total adopting employers; required for PEP."
                  },
                  "small_adopter_count": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000000,
                    "description": "Adopters with fewer than 100 participants; required for PEP."
                  },
                  "large_adopter_count": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000000,
                    "description": "Adopters with 100 or more participants; required for PEP."
                  },
                  "plan_years": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "2024",
                        "2025",
                        "2026"
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 3,
                    "uniqueItems": true
                  },
                  "referral_source": {
                    "type": "string",
                    "enum": [
                      "recordkeeper",
                      "payroll_provider",
                      "plan_advisor",
                      "tpa",
                      "pcg",
                      "linkedin",
                      "google",
                      "podcast",
                      "other"
                    ],
                    "description": "How the user heard about Pepper. Partner pages supply their existing default."
                  },
                  "referral_source_other": {
                    "type": "string",
                    "description": "Required for other referral source.",
                    "maxLength": 200
                  },
                  "promo_code": {
                    "type": "string",
                    "description": "Optional user-supplied promo code.",
                    "maxLength": 500
                  },
                  "ref_code": {
                    "type": "string",
                    "pattern": "^[A-Za-z0-9_-]{2,64}$",
                    "description": "Partner ref from the user’s Pepper link. Preserve it; do not invent one."
                  },
                  "idempotency_key": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{64}$",
                    "description": "Generate 32 cryptographically random bytes as lowercase hex; keep this private and reuse it with identical details for every retry. Never put it in URLs or logs."
                  }
                },
                "required": [
                  "plan_type",
                  "company_name",
                  "plan_name",
                  "contact_name",
                  "contact_email",
                  "state",
                  "plan_years",
                  "referral_source",
                  "idempotency_key"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success. Quote creation returns ok, proposal_url, total_fee (whole USD), currency, line_items, replayed and next_action. Lookup returns ok, found, public plan details when found, and next_action.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid fields. Inspect code, field_errors and next_action.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "403": {
            "description": "Browser origin is not allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "409": {
            "description": "Replay or promo conflict; changes were not saved.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "413": {
            "description": "Request exceeds 16 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "415": {
            "description": "Send application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "422": {
            "description": "Custom pricing requires contacting Pepper.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit. Retry after the indicated delay with the same key and details.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retry."
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable or outcome_unknown. For unknown creation outcomes retry identical details and the same idempotency_key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/plan-lookup": {
      "post": {
        "operationId": "lookup_plan",
        "summary": "Look up public plan details",
        "description": "Lookup by EIN is optional. Ask the user to confirm found details. A miss permits manual entry and must not block quote creation.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ein": {
                    "type": "string",
                    "pattern": "^\\d{2}-\\d{7}$"
                  }
                },
                "required": [
                  "ein"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success. Quote creation returns ok, proposal_url, total_fee (whole USD), currency, line_items, replayed and next_action. Lookup returns ok, found, public plan details when found, and next_action.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid fields. Inspect code, field_errors and next_action.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "403": {
            "description": "Browser origin is not allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "409": {
            "description": "Replay or promo conflict; changes were not saved.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "413": {
            "description": "Request exceeds 16 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "415": {
            "description": "Send application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "422": {
            "description": "Custom pricing requires contacting Pepper.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit. Retry after the indicated delay with the same key and details.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retry."
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable or outcome_unknown. For unknown creation outcomes retry identical details and the same idempotency_key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  }
}
