{
  "openapi": "3.1.0",
  "info": {
    "title": "Undergrads moving quote requests",
    "version": "1.0.0",
    "description": "Non-binding moving labor requests by customers or authorized assistants. No account required. No booking, price guarantee or payment. Native form: https://undergrads.com/agent-moving-quotes/. Max body: 16 KiB. Do not submit the example as a real lead. URL-encoded requests receive HTML unless Accept: application/json is supplied; JSON requests receive JSON.",
    "contact": {
      "name": "Undergrads Moving",
      "url": "https://undergrads.com/contact/"
    },
    "termsOfService": "https://undergrads.com/liability-release/"
  },
  "servers": [
    {
      "url": "https://undergrads.com"
    }
  ],
  "paths": {
    "/api/moving-requests/": {
      "post": {
        "operationId": "requestMovingQuote",
        "summary": "Request an email quote or a phone callback",
        "security": [],
        "description": "Only submit with customer permission. On delivery_unconfirmed, retry the identical payload and key with exponential backoff, at most 3 attempts, within 24 hours. After continued failure, stop and report receipt is unconfirmed. Never change a key merely because a response was lost. Use server-to-server JSON or the same-origin native form; cross-origin browser requests are rejected. Do not poll or scrape this endpoint.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MovingRequest"
              },
              "example": {
                "customerName": "Example Customer",
                "contactPreference": "email",
                "email": "customer@example.com",
                "requesterType": "assistant",
                "assistantName": "Example assistant",
                "originZip": "28202",
                "service": "loading",
                "authorized": true,
                "idempotencyKey": "example-replace-with-unique-uuid"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "customerName",
                  "contactPreference",
                  "requesterType",
                  "originZip",
                  "service",
                  "authorized",
                  "idempotencyKey"
                ],
                "properties": {
                  "customerName": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "email": {
                    "type": "string",
                    "maxLength": 254,
                    "description": "Required for email follow-up. Valid email or empty string."
                  },
                  "phone": {
                    "type": "string",
                    "maxLength": 32,
                    "description": "Required for a callback. US phone number; formatting and +1 accepted."
                  },
                  "assistantName": {
                    "type": "string",
                    "maxLength": 80,
                    "description": "Required for assistant requesters. Identify the actual assistant or service."
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 2000,
                    "description": "Optional home size, stairs, items, timing and rental truck needs. No payment details or sensitive documents."
                  },
                  "moveDate": {
                    "type": "string",
                    "maxLength": 10,
                    "description": "Optional upcoming real date YYYY-MM-DD. Leave empty or omit if flexible; never guess."
                  },
                  "contactPreference": {
                    "type": "string",
                    "enum": [
                      "email",
                      "phone"
                    ]
                  },
                  "requesterType": {
                    "type": "string",
                    "enum": [
                      "customer",
                      "assistant"
                    ]
                  },
                  "service": {
                    "type": "string",
                    "enum": [
                      "loading",
                      "unloading",
                      "loading-and-unloading",
                      "in-home",
                      "not-sure"
                    ]
                  },
                  "originZip": {
                    "type": "string",
                    "pattern": "^[0-9]{5}$",
                    "description": "ZIP where help is needed. The team confirms coverage and availability."
                  },
                  "destinationZip": {
                    "type": "string",
                    "pattern": "^([0-9]{5})?$"
                  },
                  "authorized": {
                    "type": "string",
                    "enum": [
                      "true"
                    ]
                  },
                  "idempotencyKey": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9_-]{16,64}$",
                    "description": "Unique per request. Reuse with identical fields for retries within 24 hours. Use a new key only when changing the request. Do not retry blindly after 24 hours; call the team."
                  }
                },
                "allOf": [
                  {
                    "if": {
                      "properties": {
                        "contactPreference": {
                          "const": "email"
                        }
                      }
                    },
                    "then": {
                      "required": [
                        "email"
                      ],
                      "properties": {
                        "email": {
                          "minLength": 1
                        }
                      }
                    }
                  },
                  {
                    "if": {
                      "properties": {
                        "contactPreference": {
                          "const": "phone"
                        }
                      }
                    },
                    "then": {
                      "required": [
                        "phone"
                      ],
                      "properties": {
                        "phone": {
                          "minLength": 1
                        }
                      }
                    }
                  },
                  {
                    "if": {
                      "properties": {
                        "requesterType": {
                          "const": "assistant"
                        }
                      }
                    },
                    "then": {
                      "required": [
                        "assistantName"
                      ],
                      "properties": {
                        "assistantName": {
                          "minLength": 1
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "Malformed body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Cross-origin browser request rejected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "request_in_progress: wait and retry identical fields/key. request_key_conflict: key was used for different details; only use a new key for an intentional new request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "413": {
            "description": "Body exceeds 16 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported media type.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "description": "Correct the named validation errors.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "503": {
            "description": "Delivery unavailable or unconfirmed. No confirmed receipt is claimed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "200": {
            "description": "Accepted by the delivery provider for the team. This is not a reservation or proof of inbox delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Receipt"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "MovingRequest": {
        "type": "object",
        "required": [
          "customerName",
          "contactPreference",
          "requesterType",
          "originZip",
          "service",
          "authorized",
          "idempotencyKey"
        ],
        "properties": {
          "customerName": {
            "type": "string",
            "maxLength": 100
          },
          "email": {
            "type": "string",
            "maxLength": 254,
            "description": "Required for email follow-up. Valid email or empty string."
          },
          "phone": {
            "type": "string",
            "maxLength": 32,
            "description": "Required for a callback. US phone number; formatting and +1 accepted."
          },
          "assistantName": {
            "type": "string",
            "maxLength": 80,
            "description": "Required for assistant requesters. Identify the actual assistant or service."
          },
          "notes": {
            "type": "string",
            "maxLength": 2000,
            "description": "Optional home size, stairs, items, timing and rental truck needs. No payment details or sensitive documents."
          },
          "moveDate": {
            "type": "string",
            "maxLength": 10,
            "description": "Optional upcoming real date YYYY-MM-DD. Leave empty or omit if flexible; never guess."
          },
          "contactPreference": {
            "type": "string",
            "enum": [
              "email",
              "phone"
            ]
          },
          "requesterType": {
            "type": "string",
            "enum": [
              "customer",
              "assistant"
            ]
          },
          "service": {
            "type": "string",
            "enum": [
              "loading",
              "unloading",
              "loading-and-unloading",
              "in-home",
              "not-sure"
            ]
          },
          "originZip": {
            "type": "string",
            "pattern": "^[0-9]{5}$",
            "description": "ZIP where help is needed. The team confirms coverage and availability."
          },
          "destinationZip": {
            "type": "string",
            "pattern": "^([0-9]{5})?$"
          },
          "authorized": {
            "type": "boolean",
            "const": true,
            "description": "Explicit customer permission to share these details and request follow-up by the chosen method. Never infer permission."
          },
          "idempotencyKey": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{16,64}$",
            "description": "Unique per request. Reuse with identical fields for retries within 24 hours. Use a new key only when changing the request. Do not retry blindly after 24 hours; call the team."
          }
        },
        "allOf": [
          {
            "if": {
              "properties": {
                "contactPreference": {
                  "const": "email"
                }
              }
            },
            "then": {
              "required": [
                "email"
              ],
              "properties": {
                "email": {
                  "minLength": 1
                }
              }
            }
          },
          {
            "if": {
              "properties": {
                "contactPreference": {
                  "const": "phone"
                }
              }
            },
            "then": {
              "required": [
                "phone"
              ],
              "properties": {
                "phone": {
                  "minLength": 1
                }
              }
            }
          },
          {
            "if": {
              "properties": {
                "requesterType": {
                  "const": "assistant"
                }
              }
            },
            "then": {
              "required": [
                "assistantName"
              ],
              "properties": {
                "assistantName": {
                  "minLength": 1
                }
              }
            }
          }
        ]
      },
      "Receipt": {
        "type": "object",
        "required": [
          "status",
          "requestId",
          "contactPreference",
          "bookingConfirmed",
          "message"
        ],
        "properties": {
          "status": {
            "const": "received"
          },
          "requestId": {
            "type": "string"
          },
          "contactPreference": {
            "enum": [
              "email",
              "phone"
            ]
          },
          "bookingConfirmed": {
            "const": false
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "retryable": {
            "type": "boolean"
          }
        }
      }
    }
  },
  "externalDocs": {
    "description": "Human-readable guide and native form",
    "url": "https://undergrads.com/agent-moving-quotes/"
  }
}