{
  "openapi": "3.1.0",
  "info": {
    "title": "MailKey API",
    "version": "1.0.0",
    "description": "Turn the MailKey a person gives you into their exact name and current mailing address, with their consent, and keep it current while they let you.\n\nA MailKey is 10 characters in three groups, such as K7M-XQQ-D9RA. The flow:\n\n1. **Preview.** POST /v1/previews with the key. Read the masked name and locality back to the person.\n2. **Claim.** POST /v1/grants with the preview_id inside the claim window. Some people approve each claim in the MailKey app first; you get 202 and a grant.approved webhook when they do.\n3. **Read.** GET /v1/grants/{id} whenever you mail something. Names come back exactly as the person typed them, and addresses are USPS-standardized.\n4. **Release.** DELETE /v1/grants/{id} when you no longer need the address.\n\nAuthenticate with a live API key from the business console, sent as `Authorization: Bearer mk_live_...`. Every error shares one envelope, `{\"error\": {\"code\", \"message\", \"request_id\"}}`, and every response carries the same id in the X-Request-Id header.\n\nGuides, the MCP server for AI assistants and webhook verification are at https://developers.mkey.ai."
  },
  "externalDocs": {
    "description": "MailKey for developers",
    "url": "https://developers.mkey.ai"
  },
  "servers": [
    {
      "url": "https://api.mkey.ai",
      "description": "Production"
    },
    {
      "url": "https://api-staging.mkey.ai",
      "description": "Staging"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Previews",
      "description": "Look a MailKey up and read the masked name and locality back to the person before you claim it."
    },
    {
      "name": "Grants",
      "description": "Claim a preview with the person's consent, read their current name and address while the grant lasts, and release it or report returned mail."
    },
    {
      "name": "Keys",
      "description": "Turn what a caller said into the valid keys it could mean."
    },
    {
      "name": "Status",
      "description": "Your plan's limits and today's usage."
    },
    {
      "name": "Voice agents",
      "description": "Tools for a voice agent taking a key over the phone: each answer carries a sentence to say, and previews are bound to the call. The same tools are served over MCP at mcp.mkey.ai/business."
    },
    {
      "name": "Webhooks",
      "description": "Register endpoints that receive a signed event when a grant, or the name or address behind it, changes."
    },
    {
      "name": "Webhook events",
      "description": "The signed POSTs MailKey sends to your endpoints. None carries person data; read the grant for the current name and address."
    }
  ],
  "paths": {
    "/v1/previews": {
      "post": {
        "operationId": "createPreview",
        "tags": [
          "Previews"
        ],
        "summary": "Look up a key",
        "description": "Looks up the key the person gave you and returns a masked preview: the given name, the family initial and the city. Read it back so the person can confirm it is theirs, then claim it before expires_at. A key that is not well formed answers 400 invalid_key_format and is not counted against your limits. Each lookup counts against your daily preview limit.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreviewRequest"
              },
              "examples": {
                "lookup": {
                  "summary": "A key as typed",
                  "value": {
                    "key": "K7M-XQQ-D9RA"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The masked preview.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preview"
                },
                "examples": {
                  "preview": {
                    "summary": "A masked preview",
                    "value": {
                      "preview_id": "0199a3b2-1f4e-7a6b-9c8d-2e3f4a5b6c7d",
                      "display": {
                        "name": "Zoë v.",
                        "locality": "WASHINGTON, DC"
                      },
                      "expires_at": "2026-10-01T15:14:05.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request or one of its fields is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "invalid_request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "key: Invalid input: expected string, received undefined",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "invalid_key_format": {
                    "summary": "invalid_key_format",
                    "value": {
                      "error": {
                        "code": "invalid_key_format",
                        "message": "That is not a valid MailKey; check the key with the caller.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing of yours has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "key_not_found": {
                    "summary": "key_not_found",
                    "value": {
                      "error": {
                        "code": "key_not_found",
                        "message": "No MailKey matches that key.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "MailKey cannot read person data right now; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "crypto_unavailable": {
                    "summary": "crypto_unavailable",
                    "value": {
                      "error": {
                        "code": "crypto_unavailable",
                        "message": "MailKey cannot read person data right now; try again shortly.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/grants": {
      "post": {
        "operationId": "createGrant",
        "tags": [
          "Grants"
        ],
        "summary": "Claim a preview",
        "description": "Claims a preview you made, after the person confirmed the read-back. Answers 201 with the name and address when the grant is active, or 202 when the person approves each claim in the MailKey app; a grant.approved or grant.denied webhook follows. Claiming the same preview again answers as the grant stands now: 201 while it is active, 200 without person data when it is not, for example when the person declined it.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClaimRequest"
              },
              "examples": {
                "claim": {
                  "summary": "Claim with your own reference",
                  "value": {
                    "preview_id": "0199a3b2-1f4e-7a6b-9c8d-2e3f4a5b6c7d",
                    "external_ref": "CUST-1042"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The grant is not active, so it carries no person data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Grant"
                },
                "examples": {
                  "declined": {
                    "summary": "The person declined",
                    "value": {
                      "id": "0199a3b4-0a1b-7c2d-8e3f-4a5b6c7d8e9f",
                      "status": "denied",
                      "external_ref": null,
                      "claimed_at": "2026-10-02T09:41:27.000Z"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "An active grant with the person's name and address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Grant"
                },
                "examples": {
                  "active": {
                    "summary": "An active grant",
                    "value": {
                      "id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "status": "active",
                      "external_ref": "CUST-1042",
                      "claimed_at": "2026-10-01T15:05:12.000Z",
                      "name": {
                        "given_name": "Zoë",
                        "middle_name": null,
                        "family_name": "van der Berg",
                        "suffix": null,
                        "mailing_name": null
                      },
                      "address": {
                        "line1": "1600 PENNSYLVANIA AVE NW",
                        "line2": "",
                        "city": "WASHINGTON",
                        "state": "DC",
                        "zip5": "20500",
                        "zip4": "0005",
                        "label_lines": [
                          "Zoë van der Berg",
                          "1600 PENNSYLVANIA AVE NW",
                          "WASHINGTON DC 20500-0005"
                        ]
                      },
                      "confirmed_at": "2026-09-14T18:30:00.000Z",
                      "stale": false
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "The person must approve the claim in the MailKey app.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PendingGrant"
                },
                "examples": {
                  "pending": {
                    "summary": "Waiting for approval",
                    "value": {
                      "id": "0199a3b4-0a1b-7c2d-8e3f-4a5b6c7d8e9f",
                      "status": "pending_approval"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request or one of its fields is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "invalid_request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "preview_id: Invalid UUID",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "invalid_external_ref": {
                    "summary": "invalid_external_ref",
                    "value": {
                      "error": {
                        "code": "invalid_external_ref",
                        "message": "external_ref must be at most 200 characters without control characters.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing of yours has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "preview_not_found": {
                    "summary": "preview_not_found",
                    "value": {
                      "error": {
                        "code": "preview_not_found",
                        "message": "No claimable preview has that id.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "410": {
            "description": "Gone: the claim window ended, the key is retired, or the person revoked the grant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "claim_window_expired": {
                    "summary": "claim_window_expired",
                    "value": {
                      "error": {
                        "code": "claim_window_expired",
                        "message": "The claim window for that preview has ended; look the key up again.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "key_not_usable": {
                    "summary": "key_not_usable",
                    "value": {
                      "error": {
                        "code": "key_not_usable",
                        "message": "That key can no longer be claimed.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "MailKey cannot read person data right now; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "crypto_unavailable": {
                    "summary": "crypto_unavailable",
                    "value": {
                      "error": {
                        "code": "crypto_unavailable",
                        "message": "MailKey cannot read person data right now; try again shortly.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listGrants",
        "tags": [
          "Grants"
        ],
        "summary": "List grants",
        "description": "Newest first, at most 50 a page; pass next_cursor back as cursor for the next page. With updated_since, only grants with a change you can see at or after that time, as the Changes view in the console shows them. Name and address appear only on active grants.",
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "schema": {
              "$ref": "#/components/schemas/GrantStatus"
            }
          },
          {
            "in": "query",
            "name": "updated_since",
            "schema": {
              "description": "ISO 8601. Only grants whose data visible to you changed at or after this time: an address change, a scheduled move, a confirmation, a name change or a revocation. A bare date means midnight UTC.",
              "example": "2026-10-01T00:00:00Z",
              "anyOf": [
                {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                },
                {
                  "type": "string",
                  "format": "date",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                }
              ]
            },
            "description": "ISO 8601. Only grants whose data visible to you changed at or after this time: an address change, a scheduled move, a confirmation, a name change or a revocation. A bare date means midnight UTC."
          },
          {
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "The next_cursor of the previous page.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "description": "The next_cursor of the previous page."
          }
        ],
        "responses": {
          "200": {
            "description": "One page of grants.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GrantList"
                },
                "examples": {
                  "page": {
                    "summary": "An active and a pending grant",
                    "value": {
                      "data": [
                        {
                          "id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                          "status": "active",
                          "external_ref": "CUST-1042",
                          "claimed_at": "2026-10-01T15:05:12.000Z",
                          "name": {
                            "given_name": "Zoë",
                            "middle_name": null,
                            "family_name": "van der Berg",
                            "suffix": null,
                            "mailing_name": null
                          },
                          "address": {
                            "line1": "1600 PENNSYLVANIA AVE NW",
                            "line2": "",
                            "city": "WASHINGTON",
                            "state": "DC",
                            "zip5": "20500",
                            "zip4": "0005",
                            "label_lines": [
                              "Zoë van der Berg",
                              "1600 PENNSYLVANIA AVE NW",
                              "WASHINGTON DC 20500-0005"
                            ]
                          },
                          "confirmed_at": "2026-09-14T18:30:00.000Z",
                          "stale": false
                        },
                        {
                          "id": "0199a3b4-0a1b-7c2d-8e3f-4a5b6c7d8e9f",
                          "status": "pending_approval",
                          "external_ref": null,
                          "claimed_at": "2026-10-02T09:41:27.000Z"
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request or one of its fields is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "invalid_request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "status: Invalid option: expected one of \"pending_approval\"|\"active\"|\"denied\"|\"revoked\"|\"released\"",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "MailKey cannot read person data right now; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "crypto_unavailable": {
                    "summary": "crypto_unavailable",
                    "value": {
                      "error": {
                        "code": "crypto_unavailable",
                        "message": "MailKey cannot read person data right now; try again shortly.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/grants/{id}": {
      "get": {
        "operationId": "getGrant",
        "tags": [
          "Grants"
        ],
        "summary": "Read current data",
        "description": "The grant and, while it is active, the person's current name and address. Read it whenever you mail something rather than keeping a copy. While a scheduled move keeps this grant, upcoming_address and effective_date show where the person is going. A revoked grant answers 410; delete what you hold.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "The grant with the person's data while it is active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Grant"
                },
                "examples": {
                  "active": {
                    "summary": "An active grant",
                    "value": {
                      "id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "status": "active",
                      "external_ref": "CUST-1042",
                      "claimed_at": "2026-10-01T15:05:12.000Z",
                      "name": {
                        "given_name": "Zoë",
                        "middle_name": null,
                        "family_name": "van der Berg",
                        "suffix": null,
                        "mailing_name": null
                      },
                      "address": {
                        "line1": "1600 PENNSYLVANIA AVE NW",
                        "line2": "",
                        "city": "WASHINGTON",
                        "state": "DC",
                        "zip5": "20500",
                        "zip4": "0005",
                        "label_lines": [
                          "Zoë van der Berg",
                          "1600 PENNSYLVANIA AVE NW",
                          "WASHINGTON DC 20500-0005"
                        ]
                      },
                      "confirmed_at": "2026-09-14T18:30:00.000Z",
                      "stale": false
                    }
                  },
                  "moving": {
                    "summary": "An active grant with a scheduled move",
                    "value": {
                      "id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "status": "active",
                      "external_ref": "CUST-1042",
                      "claimed_at": "2026-10-01T15:05:12.000Z",
                      "name": {
                        "given_name": "Zoë",
                        "middle_name": null,
                        "family_name": "van der Berg",
                        "suffix": null,
                        "mailing_name": null
                      },
                      "address": {
                        "line1": "1600 PENNSYLVANIA AVE NW",
                        "line2": "",
                        "city": "WASHINGTON",
                        "state": "DC",
                        "zip5": "20500",
                        "zip4": "0005",
                        "label_lines": [
                          "Zoë van der Berg",
                          "1600 PENNSYLVANIA AVE NW",
                          "WASHINGTON DC 20500-0005"
                        ]
                      },
                      "confirmed_at": "2026-09-14T18:30:00.000Z",
                      "stale": false,
                      "upcoming_address": {
                        "line1": "350 5TH AVE",
                        "line2": "STE 3400",
                        "city": "NEW YORK",
                        "state": "NY",
                        "zip5": "10118",
                        "zip4": "0110",
                        "label_lines": [
                          "Zoë van der Berg",
                          "350 5TH AVE",
                          "STE 3400",
                          "NEW YORK NY 10118-0110"
                        ]
                      },
                      "effective_date": "2026-11-01"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing of yours has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "grant_not_found": {
                    "summary": "grant_not_found",
                    "value": {
                      "error": {
                        "code": "grant_not_found",
                        "message": "No grant of yours has that id.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "410": {
            "description": "Gone: the claim window ended, the key is retired, or the person revoked the grant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "grant_revoked": {
                    "summary": "grant_revoked",
                    "value": {
                      "error": {
                        "code": "grant_revoked",
                        "message": "The person revoked this grant; delete the address you hold.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "MailKey cannot read person data right now; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "crypto_unavailable": {
                    "summary": "crypto_unavailable",
                    "value": {
                      "error": {
                        "code": "crypto_unavailable",
                        "message": "MailKey cannot read person data right now; try again shortly.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "releaseGrant",
        "tags": [
          "Grants"
        ],
        "summary": "Release a grant",
        "description": "Tells MailKey you no longer need the address. The business terms require you to delete the name and address you hold.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "The released grant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleasedGrant"
                },
                "examples": {
                  "released": {
                    "summary": "A released grant",
                    "value": {
                      "id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "status": "released",
                      "released_at": "2026-10-02T09:41:27.000Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing of yours has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "grant_not_found": {
                    "summary": "grant_not_found",
                    "value": {
                      "error": {
                        "code": "grant_not_found",
                        "message": "No grant of yours has that id.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The grant, endpoint or call does not allow this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "grant_not_active": {
                    "summary": "grant_not_active",
                    "value": {
                      "error": {
                        "code": "grant_not_active",
                        "message": "Only an active grant allows this.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/grants/{id}/returned-mail": {
      "post": {
        "operationId": "reportReturnedMail",
        "tags": [
          "Grants"
        ],
        "summary": "Report returned mail",
        "description": "Tells MailKey that mail to this grant's address came back. MailKey asks the person to confirm or update their address; resolution records what they did. Reporting again while a report is open answers 200 with that report.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "The report already open for this grant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReturnedMailReport"
                },
                "examples": {
                  "open": {
                    "summary": "An open report",
                    "value": {
                      "id": "0199a3c0-2b3c-7d4e-9f5a-6b7c8d9e0f12",
                      "grant_id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "external_ref": "CUST-1042",
                      "reported_at": "2026-10-02T09:41:27.000Z",
                      "resolution": null,
                      "resolved_at": null,
                      "flagged": false
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "The new report.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReturnedMailReport"
                },
                "examples": {
                  "open": {
                    "summary": "An open report",
                    "value": {
                      "id": "0199a3c0-2b3c-7d4e-9f5a-6b7c8d9e0f12",
                      "grant_id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "external_ref": "CUST-1042",
                      "reported_at": "2026-10-02T09:41:27.000Z",
                      "resolution": null,
                      "resolved_at": null,
                      "flagged": false
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing of yours has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "grant_not_found": {
                    "summary": "grant_not_found",
                    "value": {
                      "error": {
                        "code": "grant_not_found",
                        "message": "No grant of yours has that id.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The grant, endpoint or call does not allow this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "grant_not_active": {
                    "summary": "grant_not_active",
                    "value": {
                      "error": {
                        "code": "grant_not_active",
                        "message": "Only an active grant allows this.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/status": {
      "get": {
        "operationId": "getStatus",
        "tags": [
          "Status"
        ],
        "summary": "Plan and usage",
        "description": "Your business, its plan's limits, and today's usage. Never counted against your limits, so it is a safe way to check a key.",
        "responses": {
          "200": {
            "description": "The plan's limits and current usage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Status"
                },
                "examples": {
                  "status": {
                    "summary": "A business on the free plan",
                    "value": {
                      "business": {
                        "id": "0199a3b0-5c1d-7e2f-8a4b-6c7d8e9f0a1b",
                        "name": "Example Outfitters"
                      },
                      "plan": {
                        "name": "free",
                        "requests_per_minute": 60,
                        "previews_per_day": 2000
                      },
                      "usage": {
                        "active_grants": 42,
                        "previews_today": 7
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/keys/decode": {
      "post": {
        "operationId": "decodeTranscript",
        "tags": [
          "Keys"
        ],
        "summary": "Decode a transcript",
        "description": "Returns the valid keys a spoken or misheard key could mean, best first, without looking any of them up. At most 60 a minute per API key, separate from your request limit.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DecodeRequest"
              },
              "examples": {
                "nato": {
                  "summary": "A key read out in NATO words",
                  "value": {
                    "transcript": "kilo seven mike x-ray quebec quebec delta nine romeo alfa"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Candidate keys, best first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DecodeResponse"
                },
                "examples": {
                  "decoded": {
                    "summary": "One candidate",
                    "value": {
                      "keys": [
                        {
                          "key": "K7MXQQD9RA",
                          "formatted": "K7M-XQQ-D9RA"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request or one of its fields is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "invalid_request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "transcript: Invalid input: expected string, received undefined",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "transcript_too_long": {
                    "summary": "transcript_too_long",
                    "value": {
                      "error": {
                        "code": "transcript_too_long",
                        "message": "transcript must be at most 500 characters.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/voice/business": {
      "get": {
        "operationId": "voiceBusiness",
        "tags": [
          "Voice agents"
        ],
        "summary": "Check the key",
        "description": "The business the API key belongs to and its call rules. Never counted against your limits; use it to check a voice platform's setup.",
        "responses": {
          "200": {
            "description": "The business.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceBusiness"
                },
                "examples": {
                  "business": {
                    "summary": "A business and its call rules",
                    "value": {
                      "business": {
                        "id": "0199a3b0-5c1d-7e2f-8a4b-6c7d8e9f0a1b",
                        "name": "Example Outfitters"
                      },
                      "claim_window_minutes": 10,
                      "previews_per_call": 3
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/voice/decode": {
      "post": {
        "operationId": "voiceDecodeKey",
        "tags": [
          "Voice agents"
        ],
        "summary": "decode_key",
        "description": "The valid keys a caller's spoken key could mean, best first, each with a NATO reading in its three groups to read back. Looks nothing up.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DecodeRequest"
              },
              "examples": {
                "heard": {
                  "summary": "What the agent heard",
                  "value": {
                    "transcript": "kilo seven mike x-ray quebec quebec delta nine romeo alfa"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Candidate keys, best first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceDecodeResponse"
                },
                "examples": {
                  "decoded": {
                    "summary": "One candidate",
                    "value": {
                      "keys": [
                        {
                          "key": "K7MXQQD9RA",
                          "formatted": "K7M-XQQ-D9RA",
                          "spoken": "Kilo Seven Mike, X-ray Quebec Quebec, Delta Nine Romeo Alfa"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request or one of its fields is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "invalid_request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "transcript: Invalid input: expected string, received undefined",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "transcript_too_long": {
                    "summary": "transcript_too_long",
                    "value": {
                      "error": {
                        "code": "transcript_too_long",
                        "message": "transcript must be at most 500 characters.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/voice/previews": {
      "post": {
        "operationId": "voicePreviewKey",
        "tags": [
          "Voice agents"
        ],
        "summary": "preview_key",
        "description": "Looks a key up for the call and returns the masked preview, with a sentence to read back. At most 3 per call, on top of the business's limits. A minor's key answers 404 like an unknown key.",
        "parameters": [
          {
            "in": "header",
            "name": "x-call-id",
            "schema": {
              "description": "The call or conversation id. Previews are bound to it; a claim must come from the same call.",
              "type": "string",
              "maxLength": 128
            },
            "description": "The call or conversation id. Previews are bound to it; a claim must come from the same call."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VoicePreviewRequest"
              },
              "examples": {
                "lookup": {
                  "summary": "A key with the call id in the body",
                  "value": {
                    "key": "K7M-XQQ-D9RA",
                    "call_id": "conv_01k6m9x2y3z4"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The masked preview.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoicePreview"
                },
                "examples": {
                  "preview": {
                    "summary": "A masked preview to read back",
                    "value": {
                      "preview_id": "0199a3b2-1f4e-7a6b-9c8d-2e3f4a5b6c7d",
                      "display": {
                        "name": "Zoë v.",
                        "locality": "WASHINGTON, DC"
                      },
                      "expires_at": "2026-10-01T15:14:05.000Z",
                      "say": "Zoë v. in Washington, District of Columbia",
                      "previews_left": 2
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request or one of its fields is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "call_id_required": {
                    "summary": "call_id_required",
                    "value": {
                      "error": {
                        "code": "call_id_required",
                        "message": "Send the call's id as the X-Call-Id header or as call_id.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "invalid_call_id": {
                    "summary": "invalid_call_id",
                    "value": {
                      "error": {
                        "code": "invalid_call_id",
                        "message": "call_id must be 1 to 128 printable characters without spaces.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "invalid_request": {
                    "summary": "invalid_request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "key: Invalid input: expected string, received undefined",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "invalid_key_format": {
                    "summary": "invalid_key_format",
                    "value": {
                      "error": {
                        "code": "invalid_key_format",
                        "message": "That is not a valid MailKey. Read the key back to the caller group by group, or call decode_key with what you heard.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing of yours has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "key_not_found": {
                    "summary": "key_not_found",
                    "value": {
                      "error": {
                        "code": "key_not_found",
                        "message": "No MailKey matches that key. Ask the caller to read it again, one group at a time.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "call_preview_limit": {
                    "summary": "call_preview_limit",
                    "value": {
                      "error": {
                        "code": "call_preview_limit",
                        "message": "This call has used its 3 key lookups. Ask the caller to check their key in the MailKey app and call back.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "MailKey cannot read person data right now; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "crypto_unavailable": {
                    "summary": "crypto_unavailable",
                    "value": {
                      "error": {
                        "code": "crypto_unavailable",
                        "message": "MailKey cannot read person data right now; try again shortly.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/voice/grants": {
      "post": {
        "operationId": "voiceClaimKey",
        "tags": [
          "Voice agents"
        ],
        "summary": "claim_key",
        "description": "Claims a preview made on the same call, inside the business's claim window, after the caller confirmed the read-back. The same approval rules apply as for a person at your business, and the audit trail records the voice agent.",
        "parameters": [
          {
            "in": "header",
            "name": "x-call-id",
            "schema": {
              "description": "The call or conversation id. Previews are bound to it; a claim must come from the same call.",
              "type": "string",
              "maxLength": 128
            },
            "description": "The call or conversation id. Previews are bound to it; a claim must come from the same call."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VoiceClaimRequest"
              },
              "examples": {
                "claim": {
                  "summary": "Claim on the same call",
                  "value": {
                    "preview_id": "0199a3b2-1f4e-7a6b-9c8d-2e3f4a5b6c7d",
                    "call_id": "conv_01k6m9x2y3z4",
                    "external_ref": "CUST-1042"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The grant is not active, so it carries no person data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceGrant"
                },
                "examples": {
                  "declined": {
                    "summary": "The person declined",
                    "value": {
                      "id": "0199a3b4-0a1b-7c2d-8e3f-4a5b6c7d8e9f",
                      "status": "denied",
                      "external_ref": null,
                      "claimed_at": "2026-10-02T09:41:27.000Z",
                      "say": "This address is not shared with us."
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "An active grant with the person's name and address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceGrant"
                },
                "examples": {
                  "active": {
                    "summary": "Saved",
                    "value": {
                      "id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "status": "active",
                      "external_ref": "CUST-1042",
                      "claimed_at": "2026-10-01T15:05:12.000Z",
                      "name": {
                        "given_name": "Zoë",
                        "middle_name": null,
                        "family_name": "van der Berg",
                        "suffix": null,
                        "mailing_name": null
                      },
                      "address": {
                        "line1": "1600 PENNSYLVANIA AVE NW",
                        "line2": "",
                        "city": "WASHINGTON",
                        "state": "DC",
                        "zip5": "20500",
                        "zip4": "0005",
                        "label_lines": [
                          "Zoë van der Berg",
                          "1600 PENNSYLVANIA AVE NW",
                          "WASHINGTON DC 20500-0005"
                        ]
                      },
                      "confirmed_at": "2026-09-14T18:30:00.000Z",
                      "stale": false,
                      "say": "Thank you. Your address is saved, and MailKey will keep it current if you move."
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "The person must approve the claim in the MailKey app.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoicePendingGrant"
                },
                "examples": {
                  "pending": {
                    "summary": "Waiting for approval",
                    "value": {
                      "id": "0199a3b4-0a1b-7c2d-8e3f-4a5b6c7d8e9f",
                      "status": "pending_approval",
                      "say": "MailKey has asked you to approve this in the MailKey app. We'll have your address once you do."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request or one of its fields is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "call_id_required": {
                    "summary": "call_id_required",
                    "value": {
                      "error": {
                        "code": "call_id_required",
                        "message": "Send the call's id as the X-Call-Id header or as call_id.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "invalid_call_id": {
                    "summary": "invalid_call_id",
                    "value": {
                      "error": {
                        "code": "invalid_call_id",
                        "message": "call_id must be 1 to 128 printable characters without spaces.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "invalid_request": {
                    "summary": "invalid_request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "preview_id: Invalid UUID",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "invalid_external_ref": {
                    "summary": "invalid_external_ref",
                    "value": {
                      "error": {
                        "code": "invalid_external_ref",
                        "message": "external_ref must be at most 200 characters without control characters.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing of yours has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "preview_not_found": {
                    "summary": "preview_not_found",
                    "value": {
                      "error": {
                        "code": "preview_not_found",
                        "message": "No lookup of yours has that preview_id. Look the key up again with preview_key.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The grant, endpoint or call does not allow this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "preview_other_call": {
                    "summary": "preview_other_call",
                    "value": {
                      "error": {
                        "code": "preview_other_call",
                        "message": "That preview_id came from another call. Look the key up again on this call.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "410": {
            "description": "Gone: the claim window ended, the key is retired, or the person revoked the grant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "claim_window_expired": {
                    "summary": "claim_window_expired",
                    "value": {
                      "error": {
                        "code": "claim_window_expired",
                        "message": "The time to save this address ran out. Look the key up again and read the preview back.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "key_not_usable": {
                    "summary": "key_not_usable",
                    "value": {
                      "error": {
                        "code": "key_not_usable",
                        "message": "That key can no longer be used. Ask the caller for their current key.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "MailKey cannot read person data right now; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "crypto_unavailable": {
                    "summary": "crypto_unavailable",
                    "value": {
                      "error": {
                        "code": "crypto_unavailable",
                        "message": "MailKey cannot read person data right now; try again shortly.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/voice/grants/{id}": {
      "get": {
        "operationId": "voiceGetGrant",
        "tags": [
          "Voice agents"
        ],
        "summary": "get_grant",
        "description": "The grant and, while it is active, the person's name and address, for a grant made on an earlier call or still waiting for approval.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "The grant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Grant"
                },
                "examples": {
                  "active": {
                    "summary": "An active grant",
                    "value": {
                      "id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "status": "active",
                      "external_ref": "CUST-1042",
                      "claimed_at": "2026-10-01T15:05:12.000Z",
                      "name": {
                        "given_name": "Zoë",
                        "middle_name": null,
                        "family_name": "van der Berg",
                        "suffix": null,
                        "mailing_name": null
                      },
                      "address": {
                        "line1": "1600 PENNSYLVANIA AVE NW",
                        "line2": "",
                        "city": "WASHINGTON",
                        "state": "DC",
                        "zip5": "20500",
                        "zip4": "0005",
                        "label_lines": [
                          "Zoë van der Berg",
                          "1600 PENNSYLVANIA AVE NW",
                          "WASHINGTON DC 20500-0005"
                        ]
                      },
                      "confirmed_at": "2026-09-14T18:30:00.000Z",
                      "stale": false
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing of yours has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "grant_not_found": {
                    "summary": "grant_not_found",
                    "value": {
                      "error": {
                        "code": "grant_not_found",
                        "message": "No grant of yours has that id.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "410": {
            "description": "Gone: the claim window ended, the key is retired, or the person revoked the grant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "grant_revoked": {
                    "summary": "grant_revoked",
                    "value": {
                      "error": {
                        "code": "grant_revoked",
                        "message": "The person revoked this grant; delete the address you hold.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "MailKey cannot read person data right now; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "crypto_unavailable": {
                    "summary": "crypto_unavailable",
                    "value": {
                      "error": {
                        "code": "crypto_unavailable",
                        "message": "MailKey cannot read person data right now; try again shortly.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints": {
      "post": {
        "operationId": "createWebhookEndpoint",
        "tags": [
          "Webhooks"
        ],
        "summary": "Add a webhook endpoint",
        "description": "Returns the signing secret once; store it to verify each delivery. At most 10 endpoints per business. The URL must be https on port 443 and resolve only to public addresses; redirects are not followed.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEndpointCreate"
              },
              "examples": {
                "some": {
                  "summary": "Only the events you handle",
                  "value": {
                    "url": "https://hooks.example.com/mailkey",
                    "events": [
                      "grant.revoked",
                      "address.change_scheduled",
                      "address.changed"
                    ]
                  }
                },
                "all": {
                  "summary": "Every event type",
                  "value": {
                    "url": "https://hooks.example.com/mailkey"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The endpoint and its signing secret.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedWebhookEndpoint"
                },
                "examples": {
                  "created": {
                    "summary": "A new endpoint",
                    "value": {
                      "id": "0199a3d1-3c4d-7e5f-a06b-7c8d9e0f1a23",
                      "url": "https://hooks.example.com/mailkey",
                      "events": [
                        "grant.revoked",
                        "address.change_scheduled",
                        "address.changed"
                      ],
                      "created_at": "2026-10-01T15:04:05.000Z",
                      "failing_since": null,
                      "disabled_at": null,
                      "secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request or one of its fields is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "invalid_request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "url: Too small: expected string to have >=1 characters",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  },
                  "invalid_webhook_url": {
                    "summary": "invalid_webhook_url",
                    "value": {
                      "error": {
                        "code": "invalid_webhook_url",
                        "message": "url must use https.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The grant, endpoint or call does not allow this.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "too_many_webhook_endpoints": {
                    "summary": "too_many_webhook_endpoints",
                    "value": {
                      "error": {
                        "code": "too_many_webhook_endpoints",
                        "message": "A business can have at most 10 webhook endpoints.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "MailKey cannot read person data right now; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "crypto_unavailable": {
                    "summary": "crypto_unavailable",
                    "value": {
                      "error": {
                        "code": "crypto_unavailable",
                        "message": "MailKey cannot read person data right now; try again shortly.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listWebhookEndpoints",
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook endpoints",
        "description": "Your business's endpoints, newest first. Secrets are never shown again; failing_since and disabled_at show delivery trouble.",
        "responses": {
          "200": {
            "description": "The business's endpoints.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointList"
                },
                "examples": {
                  "list": {
                    "summary": "One endpoint",
                    "value": {
                      "data": [
                        {
                          "id": "0199a3d1-3c4d-7e5f-a06b-7c8d9e0f1a23",
                          "url": "https://hooks.example.com/mailkey",
                          "events": [
                            "grant.revoked",
                            "address.change_scheduled",
                            "address.changed"
                          ],
                          "created_at": "2026-10-01T15:04:05.000Z",
                          "failing_since": null,
                          "disabled_at": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{id}": {
      "delete": {
        "operationId": "deleteWebhookEndpoint",
        "tags": [
          "Webhooks"
        ],
        "summary": "Remove a webhook endpoint",
        "description": "Nothing more is sent to it, including retries in progress.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint is gone.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedWebhookEndpoint"
                },
                "examples": {
                  "deleted": {
                    "summary": "Removed",
                    "value": {
                      "id": "0199a3d1-3c4d-7e5f-a06b-7c8d9e0f1a23",
                      "deleted": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing of yours has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "webhook_endpoint_not_found": {
                    "summary": "webhook_endpoint_not_found",
                    "value": {
                      "error": {
                        "code": "webhook_endpoint_not_found",
                        "message": "No webhook endpoint of yours has that id.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{id}/test": {
      "post": {
        "operationId": "testWebhookEndpoint",
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a test event",
        "description": "Sends one signed webhook.test event now and reports your endpoint's answer. A success re-enables an endpoint that was disabled after 24 hours of failures.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "What your endpoint answered.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTestResult"
                },
                "examples": {
                  "delivered": {
                    "summary": "Your endpoint answered 2xx",
                    "value": {
                      "delivered": true,
                      "status_code": 200,
                      "error": null
                    }
                  },
                  "failed": {
                    "summary": "Your endpoint timed out",
                    "value": {
                      "delivered": false,
                      "status_code": null,
                      "error": "timeout"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "Send a live API key as Authorization: Bearer mk_live_...",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The business is not in production yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "business_not_in_production": {
                    "summary": "business_not_in_production",
                    "value": {
                      "error": {
                        "code": "business_not_in_production",
                        "message": "Your business is not in production yet. API keys work once MailKey approves it.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Nothing of yours has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "webhook_endpoint_not_found": {
                    "summary": "webhook_endpoint_not_found",
                    "value": {
                      "error": {
                        "code": "webhook_endpoint_not_found",
                        "message": "No webhook endpoint of yours has that id.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; retry after the number of seconds in Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                },
                "example": 42
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "rate_limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests; retry after the number of seconds in Retry-After.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "MailKey cannot read person data right now; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "crypto_unavailable": {
                    "summary": "crypto_unavailable",
                    "value": {
                      "error": {
                        "code": "crypto_unavailable",
                        "message": "MailKey cannot read person data right now; try again shortly.",
                        "request_id": "0199a5e1-4c2b-7d3e-8f4a-5b6c7d8e9f01"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "grant.approved": {
      "post": {
        "operationId": "webhook_grant_approved",
        "tags": [
          "Webhook events"
        ],
        "summary": "grant.approved",
        "description": "The person approved a claim that was waiting for them. The grant is now active; read it for the name and address. Verify the webhook-signature header with your endpoint's secret before acting on it.",
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "examples": {
                "grant.approved": {
                  "summary": "grant.approved",
                  "value": {
                    "type": "grant.approved",
                    "timestamp": "2026-10-02T09:41:27.000Z",
                    "data": {
                      "event_id": "0199a3e2-4d5e-7f60-b17c-8d9e0f1a2b34",
                      "grant_id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "external_ref": "CUST-1042",
                      "detail": {}
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the event."
          }
        }
      }
    },
    "grant.denied": {
      "post": {
        "operationId": "webhook_grant_denied",
        "tags": [
          "Webhook events"
        ],
        "summary": "grant.denied",
        "description": "The person declined a claim that was waiting for them. Verify the webhook-signature header with your endpoint's secret before acting on it.",
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "examples": {
                "grant.denied": {
                  "summary": "grant.denied",
                  "value": {
                    "type": "grant.denied",
                    "timestamp": "2026-10-02T09:41:27.000Z",
                    "data": {
                      "event_id": "0199a3e2-4d5e-7f60-b17c-8d9e0f1a2b34",
                      "grant_id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "external_ref": "CUST-1042",
                      "detail": {}
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the event."
          }
        }
      }
    },
    "grant.revoked": {
      "post": {
        "operationId": "webhook_grant_revoked",
        "tags": [
          "Webhook events"
        ],
        "summary": "grant.revoked",
        "description": "The grant ended without you releasing it, for example because the person revoked it. Delete the name and address you hold. Verify the webhook-signature header with your endpoint's secret before acting on it.",
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "examples": {
                "grant.revoked": {
                  "summary": "grant.revoked",
                  "value": {
                    "type": "grant.revoked",
                    "timestamp": "2026-10-02T09:41:27.000Z",
                    "data": {
                      "event_id": "0199a3e2-4d5e-7f60-b17c-8d9e0f1a2b34",
                      "grant_id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "external_ref": "CUST-1042",
                      "detail": {
                        "status": "revoked",
                        "reason": "person",
                        "previous_status": "active"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the event."
          }
        }
      }
    },
    "address.change_scheduled": {
      "post": {
        "operationId": "webhook_address_change_scheduled",
        "tags": [
          "Webhook events"
        ],
        "summary": "address.change_scheduled",
        "description": "The person scheduled a move that keeps this grant. detail.effective_date is the day it takes effect; the grant shows upcoming_address until then. Verify the webhook-signature header with your endpoint's secret before acting on it.",
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "examples": {
                "address.change_scheduled": {
                  "summary": "address.change_scheduled",
                  "value": {
                    "type": "address.change_scheduled",
                    "timestamp": "2026-10-02T09:41:27.000Z",
                    "data": {
                      "event_id": "0199a3e2-4d5e-7f60-b17c-8d9e0f1a2b34",
                      "grant_id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "external_ref": "CUST-1042",
                      "detail": {
                        "effective_date": "2026-11-01"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the event."
          }
        }
      }
    },
    "address.changed": {
      "post": {
        "operationId": "webhook_address_changed",
        "tags": [
          "Webhook events"
        ],
        "summary": "address.changed",
        "description": "The person's current address changed. Read the grant for the new address. Verify the webhook-signature header with your endpoint's secret before acting on it.",
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "examples": {
                "address.changed": {
                  "summary": "address.changed",
                  "value": {
                    "type": "address.changed",
                    "timestamp": "2026-10-02T09:41:27.000Z",
                    "data": {
                      "event_id": "0199a3e2-4d5e-7f60-b17c-8d9e0f1a2b34",
                      "grant_id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "external_ref": "CUST-1042",
                      "detail": {
                        "effective_date": "2026-11-01"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the event."
          }
        }
      }
    },
    "address.confirmed": {
      "post": {
        "operationId": "webhook_address_confirmed",
        "tags": [
          "Webhook events"
        ],
        "summary": "address.confirmed",
        "description": "The person confirmed their address is still current. Verify the webhook-signature header with your endpoint's secret before acting on it.",
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "examples": {
                "address.confirmed": {
                  "summary": "address.confirmed",
                  "value": {
                    "type": "address.confirmed",
                    "timestamp": "2026-10-02T09:41:27.000Z",
                    "data": {
                      "event_id": "0199a3e2-4d5e-7f60-b17c-8d9e0f1a2b34",
                      "grant_id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "external_ref": "CUST-1042",
                      "detail": {}
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the event."
          }
        }
      }
    },
    "name.changed": {
      "post": {
        "operationId": "webhook_name_changed",
        "tags": [
          "Webhook events"
        ],
        "summary": "name.changed",
        "description": "The person edited their name; detail.fields lists what changed. Read the grant for the name exactly as typed. Verify the webhook-signature header with your endpoint's secret before acting on it.",
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "examples": {
                "name.changed": {
                  "summary": "name.changed",
                  "value": {
                    "type": "name.changed",
                    "timestamp": "2026-10-02T09:41:27.000Z",
                    "data": {
                      "event_id": "0199a3e2-4d5e-7f60-b17c-8d9e0f1a2b34",
                      "grant_id": "0199a3b2-7d8e-7f90-a1b2-c3d4e5f6a7b8",
                      "external_ref": "CUST-1042",
                      "detail": {
                        "fields": [
                          "familyName"
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the event."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "PreviewRequest": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "The key as heard or typed; spaces and dashes are ignored.",
            "example": "K7M-XQQ-D9RA"
          }
        },
        "required": [
          "key"
        ]
      },
      "ClaimRequest": {
        "type": "object",
        "properties": {
          "preview_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "external_ref": {
            "description": "Your own reference for this grant, such as a customer number.",
            "type": "string",
            "maxLength": 200
          }
        },
        "required": [
          "preview_id"
        ]
      },
      "GrantStatus": {
        "type": "string",
        "enum": [
          "pending_approval",
          "active",
          "denied",
          "revoked",
          "released"
        ]
      },
      "DecodeRequest": {
        "type": "object",
        "properties": {
          "transcript": {
            "type": "string",
            "maxLength": 500,
            "description": "What the caller said or the rep heard.",
            "example": "kilo seven mike x-ray quebec quebec delta nine romeo alfa"
          }
        },
        "required": [
          "transcript"
        ]
      },
      "VoicePreviewRequest": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "The key as heard or typed; spaces and dashes are ignored.",
            "example": "K7M-XQQ-D9RA"
          },
          "call_id": {
            "description": "The voice platform's call or conversation id, when it cannot send the X-Call-Id header. The header wins when both are sent.",
            "example": "conv_01k6m9x2y3z4",
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "pattern": "^[\\x21-\\x7e]+$"
          }
        },
        "required": [
          "key"
        ]
      },
      "VoiceClaimRequest": {
        "type": "object",
        "properties": {
          "preview_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "external_ref": {
            "description": "Your own reference for this grant, such as a customer number.",
            "type": "string",
            "maxLength": 200
          },
          "call_id": {
            "description": "The voice platform's call or conversation id, when it cannot send the X-Call-Id header. The header wins when both are sent.",
            "example": "conv_01k6m9x2y3z4",
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "pattern": "^[\\x21-\\x7e]+$"
          }
        },
        "required": [
          "preview_id"
        ]
      },
      "WebhookEndpointCreate": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "description": "An https URL on port 443 whose host resolves only to public addresses. Redirects are not followed.",
            "example": "https://hooks.example.com/mailkey"
          },
          "events": {
            "description": "The event types to send; every type when omitted.",
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          }
        },
        "required": [
          "url"
        ]
      },
      "WebhookEventType": {
        "type": "string",
        "enum": [
          "grant.approved",
          "grant.denied",
          "grant.revoked",
          "address.change_scheduled",
          "address.changed",
          "address.confirmed",
          "name.changed"
        ]
      },
      "WebhookEvent": {
        "type": "object",
        "properties": {
          "type": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/WebhookEventType"
              },
              {
                "type": "string",
                "const": "webhook.test"
              }
            ]
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "description": "When the change happened."
          },
          "data": {
            "type": "object",
            "properties": {
              "event_id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "grant_id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "external_ref": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "detail": {
                "description": "What changed, without person data: for example reason, effective_date or the name fields edited. Read GET /v1/grants/{id} for the current name and address.",
                "type": "object",
                "propertyNames": {
                  "type": "string"
                },
                "additionalProperties": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "number"
                    },
                    {
                      "type": "boolean"
                    },
                    {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  ]
                }
              },
              "endpoint_id": {
                "description": "Present on webhook.test only.",
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              }
            }
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "description": "POSTed as JSON with the Standard Webhooks headers webhook-id, webhook-timestamp and webhook-signature (v1, HMAC-SHA256 of id.timestamp.body under the decoded secret). webhook-id is stable across retries; use it to drop duplicates."
      },
      "Preview": {
        "type": "object",
        "properties": {
          "preview_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "display": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "description": "Given name and the family initial, exactly as typed.",
                "example": "Zoë v."
              },
              "locality": {
                "type": "string",
                "example": "WASHINGTON, DC"
              }
            },
            "required": [
              "name",
              "locality"
            ],
            "additionalProperties": false
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "description": "The claim window ends at this time."
          }
        },
        "required": [
          "preview_id",
          "display",
          "expires_at"
        ],
        "additionalProperties": false
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "example": "key_not_found"
              },
              "message": {
                "type": "string"
              },
              "request_id": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message",
              "request_id"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "error"
        ],
        "additionalProperties": false
      },
      "Grant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "status": {
            "$ref": "#/components/schemas/GrantStatus"
          },
          "external_ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "claimed_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
          },
          "name": {
            "$ref": "#/components/schemas/Name"
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          },
          "confirmed_at": {
            "description": "When the person last entered or confirmed the address.",
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
          },
          "stale": {
            "description": "True when the address was confirmed more than 12 months ago.",
            "type": "boolean"
          },
          "upcoming_address": {
            "description": "The address the person is moving to, present while a move is scheduled that keeps this grant.",
            "$ref": "#/components/schemas/Address"
          },
          "effective_date": {
            "description": "The calendar date (UTC) upcoming_address takes effect.",
            "example": "2026-11-01",
            "type": "string",
            "format": "date",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
          }
        },
        "required": [
          "id",
          "status",
          "external_ref",
          "claimed_at"
        ],
        "additionalProperties": false,
        "description": "Name and address are present only while the grant is active. A grant a scheduled move does not keep is revoked on its effective date and shows no upcoming_address."
      },
      "Name": {
        "type": "object",
        "properties": {
          "given_name": {
            "type": "string"
          },
          "middle_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "family_name": {
            "type": "string"
          },
          "suffix": {
            "type": [
              "string",
              "null"
            ]
          },
          "mailing_name": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "given_name",
          "middle_name",
          "family_name",
          "suffix",
          "mailing_name"
        ],
        "additionalProperties": false,
        "description": "Stored and returned byte for byte as the person typed it (D33)."
      },
      "Address": {
        "type": "object",
        "properties": {
          "line1": {
            "type": "string"
          },
          "line2": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "zip5": {
            "type": "string"
          },
          "zip4": {
            "type": "string"
          },
          "label_lines": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The name and address as mailing-label lines."
          }
        },
        "required": [
          "line1",
          "line2",
          "city",
          "state",
          "zip5",
          "zip4",
          "label_lines"
        ],
        "additionalProperties": false,
        "description": "The USPS-standardized address."
      },
      "PendingGrant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "status": {
            "$ref": "#/components/schemas/GrantStatus"
          }
        },
        "required": [
          "id",
          "status"
        ],
        "additionalProperties": false
      },
      "GrantList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Grant"
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "ReleasedGrant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "status": {
            "type": "string",
            "const": "released"
          },
          "released_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
          }
        },
        "required": [
          "id",
          "status",
          "released_at"
        ],
        "additionalProperties": false
      },
      "ReturnedMailReport": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "grant_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "external_ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "reported_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
          },
          "resolution": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "confirmed",
                  "updated",
                  "no_response"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "resolved_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
              },
              {
                "type": "null"
              }
            ]
          },
          "flagged": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "grant_id",
          "external_ref",
          "reported_at",
          "resolution",
          "resolved_at",
          "flagged"
        ],
        "additionalProperties": false
      },
      "Status": {
        "type": "object",
        "properties": {
          "business": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ],
            "additionalProperties": false
          },
          "plan": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "const": "free"
              },
              "requests_per_minute": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "previews_per_day": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "name",
              "requests_per_minute",
              "previews_per_day"
            ],
            "additionalProperties": false
          },
          "usage": {
            "type": "object",
            "properties": {
              "active_grants": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "previews_today": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "active_grants",
              "previews_today"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "business",
          "plan",
          "usage"
        ],
        "additionalProperties": false
      },
      "DecodeResponse": {
        "type": "object",
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "formatted": {
                  "type": "string"
                }
              },
              "required": [
                "key",
                "formatted"
              ],
              "additionalProperties": false
            },
            "description": "At most five valid keys the transcript could mean, best first."
          }
        },
        "required": [
          "keys"
        ],
        "additionalProperties": false
      },
      "VoiceBusiness": {
        "type": "object",
        "properties": {
          "business": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ],
            "additionalProperties": false
          },
          "claim_window_minutes": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "previews_per_call": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "business",
          "claim_window_minutes",
          "previews_per_call"
        ],
        "additionalProperties": false
      },
      "VoiceDecodeResponse": {
        "type": "object",
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "formatted": {
                  "type": "string",
                  "example": "K7M-XQQ-D9RA"
                },
                "spoken": {
                  "type": "string",
                  "description": "The key in its three groups as NATO words, for reading back.",
                  "example": "Kilo Seven Mike, X-ray Quebec Quebec, Delta Nine Romeo Alfa"
                }
              },
              "required": [
                "key",
                "formatted",
                "spoken"
              ],
              "additionalProperties": false
            },
            "description": "At most five valid keys the transcript could mean, best first."
          }
        },
        "required": [
          "keys"
        ],
        "additionalProperties": false
      },
      "VoicePreview": {
        "type": "object",
        "properties": {
          "preview_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "display": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "description": "Given name and the family initial, exactly as typed.",
                "example": "Zoë v."
              },
              "locality": {
                "type": "string",
                "example": "WASHINGTON, DC"
              }
            },
            "required": [
              "name",
              "locality"
            ],
            "additionalProperties": false
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "description": "The claim window ends at this time."
          },
          "say": {
            "type": "string",
            "description": "The masked preview as a sentence to read to the caller, state spelled out.",
            "example": "Zoë v. in Washington, District of Columbia"
          },
          "previews_left": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Key lookups this call has left, out of 3."
          }
        },
        "required": [
          "preview_id",
          "display",
          "expires_at",
          "say",
          "previews_left"
        ],
        "additionalProperties": false
      },
      "VoiceGrant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "status": {
            "$ref": "#/components/schemas/GrantStatus"
          },
          "external_ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "claimed_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
          },
          "name": {
            "$ref": "#/components/schemas/Name"
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          },
          "confirmed_at": {
            "description": "When the person last entered or confirmed the address.",
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
          },
          "stale": {
            "description": "True when the address was confirmed more than 12 months ago.",
            "type": "boolean"
          },
          "upcoming_address": {
            "description": "The address the person is moving to, present while a move is scheduled that keeps this grant.",
            "$ref": "#/components/schemas/Address"
          },
          "effective_date": {
            "description": "The calendar date (UTC) upcoming_address takes effect.",
            "example": "2026-11-01",
            "type": "string",
            "format": "date",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
          },
          "say": {
            "type": "string",
            "description": "A sentence to tell the caller.",
            "example": "Thank you. Your address is saved, and MailKey will keep it current if you move."
          }
        },
        "required": [
          "id",
          "status",
          "external_ref",
          "claimed_at",
          "say"
        ],
        "additionalProperties": false
      },
      "VoicePendingGrant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "status": {
            "$ref": "#/components/schemas/GrantStatus"
          },
          "say": {
            "type": "string",
            "description": "A sentence to tell the caller.",
            "example": "MailKey has asked you to approve this in the MailKey app. We'll have your address once you do."
          }
        },
        "required": [
          "id",
          "status",
          "say"
        ],
        "additionalProperties": false
      },
      "CreatedWebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "url": {
            "type": "string"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
          },
          "failing_since": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Set while deliveries are failing and being retried; cleared by a success."
          },
          "disabled_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Set when a delivery still failed after 24 hours of retries. Nothing more is sent until a test succeeds."
          },
          "secret": {
            "type": "string",
            "description": "The signing secret, whsec_ followed by base64. Shown only in this response; MailKey cannot show it again.",
            "example": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "created_at",
          "failing_since",
          "disabled_at",
          "secret"
        ],
        "additionalProperties": false
      },
      "WebhookEndpointList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEndpoint"
            }
          }
        },
        "required": [
          "data"
        ],
        "additionalProperties": false
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "url": {
            "type": "string"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
          },
          "failing_since": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Set while deliveries are failing and being retried; cleared by a success."
          },
          "disabled_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Set when a delivery still failed after 24 hours of retries. Nothing more is sent until a test succeeds."
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "created_at",
          "failing_since",
          "disabled_at"
        ],
        "additionalProperties": false
      },
      "DeletedWebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "deleted": {
            "type": "boolean",
            "const": true
          }
        },
        "required": [
          "id",
          "deleted"
        ],
        "additionalProperties": false
      },
      "WebhookTestResult": {
        "type": "object",
        "properties": {
          "delivered": {
            "type": "boolean"
          },
          "status_code": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "Your endpoint's HTTP status."
          },
          "error": {
            "example": "timeout",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "delivered",
          "status_code",
          "error"
        ],
        "additionalProperties": false
      }
    },
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "A live API key issued from the business console: mk_live_ followed by 32 characters."
      }
    }
  }
}
