// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.maps.addressvalidation.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/maps/addressvalidation/v1/address.proto";
import "google/maps/addressvalidation/v1/geocode.proto";
import "google/maps/addressvalidation/v1/metadata.proto";
import "google/maps/addressvalidation/v1/usps_data.proto";
import "google/type/postal_address.proto";

option cc_enable_arenas = true;
option csharp_namespace = "Google.Maps.AddressValidation.V1";
option go_package = "cloud.google.com/go/maps/addressvalidation/apiv1/addressvalidationpb;addressvalidationpb";
option java_multiple_files = true;
option java_outer_classname = "AddressValidationServiceProto";
option java_package = "com.google.maps.addressvalidation.v1";
option objc_class_prefix = "GMPAVV1";
option php_namespace = "Google\\Maps\\AddressValidation\\V1";
option ruby_package = "Google::Maps::AddressValidation::V1";

// The service for validating addresses.
service AddressValidation {
  option (google.api.default_host) = "addressvalidation.googleapis.com";

  // Validates an address.
  rpc ValidateAddress(ValidateAddressRequest)
      returns (ValidateAddressResponse) {
    option (google.api.http) = {
      post: "/v1:validateAddress"
      body: "*"
    };
  }

  // Feedback about the outcome of the sequence of validation attempts. This
  // should be the last call made after a sequence of validation calls for the
  // same address, and should be called once the transaction is concluded. This
  // should only be sent once for the sequence of `ValidateAddress` requests
  // needed to validate an address fully.
  rpc ProvideValidationFeedback(ProvideValidationFeedbackRequest)
      returns (ProvideValidationFeedbackResponse) {
    option (google.api.http) = {
      post: "/v1:provideValidationFeedback"
      body: "*"
    };
  }
}

// The request for validating an address.
message ValidateAddressRequest {
  // Required. The address being validated. Unformatted addresses should be
  // submitted via [`address_lines`][google.type.PostalAddress.address_lines].
  //
  // The total length of the fields in this input must not exceed 280
  // characters.
  //
  // Supported regions can be found
  // [here](https://developers.google.com/maps/documentation/address-validation/coverage).
  //
  // The [language_code][google.type.PostalAddress.language_code] value in the
  // input address is reserved for future uses and is ignored today. The
  // validated address result will be populated based on the preferred language
  // for the given address, as identified by the system.
  //
  // The Address Validation API ignores the values in
  // [recipients][google.type.PostalAddress.recipients] and
  // [organization][google.type.PostalAddress.organization]. Any values in those
  // fields will be discarded and not returned. Please do not set them.
  google.type.PostalAddress address = 1
      [(google.api.field_behavior) = REQUIRED];

  // This field must be empty for the first address validation request. If
  // more requests are necessary to fully validate a single address (for
  // example if the changes the user makes after the initial validation need to
  // be re-validated), then each followup request must populate this field with
  // the
  // [response_id][google.maps.addressvalidation.v1.ValidateAddressResponse.response_id]
  // from the very first response in the validation sequence.
  string previous_response_id = 2;

  // Enables USPS CASS compatible mode. This affects _only_ the
  // [google.maps.addressvalidation.v1.ValidationResult.usps_data] field of
  // [google.maps.addressvalidation.v1.ValidationResult]. Note: for USPS CASS
  // enabled requests for addresses in Puerto Rico, a
  // [google.type.PostalAddress.region_code] of the `address` must be provided
  // as "PR", or an [google.type.PostalAddress.administrative_area] of the
  // `address` must be provided as "Puerto Rico" (case-insensitive) or "PR".
  //
  // It's recommended to use a componentized `address`, or alternatively specify
  // at least two [google.type.PostalAddress.address_lines] where the first line
  // contains the street number and name and the second line contains the city,
  // state, and zip code.
  bool enable_usps_cass = 3;

  // Optional. A string which identifies an Autocomplete session for billing
  // purposes. Must be a URL and filename safe base64 string with at most 36
  // ASCII characters in length. Otherwise an INVALID_ARGUMENT error is
  // returned.
  //
  // The session begins when the user starts typing a query, and concludes when
  // they select a place and a call to Place Details or Address Validation is
  // made. Each session can have multiple autocomplete queries, followed by one
  // Place Details or Address Validation request. The credentials used for each
  // request within a session must belong to the same Google Cloud Console
  // project. Once a session has concluded, the token is no longer valid; your
  // app must generate a fresh token for each session. If the `session_token`
  // parameter is omitted, or if you reuse a session token, the session is
  // charged as if no session token was provided (each request is billed
  // separately).
  //
  // Note: Address Validation can only be used in sessions with the
  // Autocomplete (New) API, not the old Autocomplete API. See
  // https://developers.google.com/maps/documentation/places/web-service/session-pricing
  // for more details.
  string session_token = 5 [(google.api.field_behavior) = OPTIONAL];
}

// The response to an address validation request.
message ValidateAddressResponse {
  // The result of the address validation.
  ValidationResult result = 1;

  // The UUID that identifies this response. If the address needs to be
  // re-validated, this UUID *must* accompany the new request.
  string response_id = 2;
}

// The request for sending validation feedback.
message ProvideValidationFeedbackRequest {
  // The possible final outcomes of the sequence of address validation requests
  // needed to validate an address.
  enum ValidationConclusion {
    // This value is unused.
    // If the `ProvideValidationFeedbackRequest.conclusion` field is set to
    // `VALIDATION_CONCLUSION_UNSPECIFIED`, an `INVALID_ARGUMENT` error will be
    // returned.
    VALIDATION_CONCLUSION_UNSPECIFIED = 0;

    // The version of the address returned by the Address Validation API was
    // used for the transaction.
    VALIDATED_VERSION_USED = 1;

    // The version of the address provided by the user was used for the
    // transaction
    USER_VERSION_USED = 2;

    // A version of the address that was entered after the last validation
    // attempt but that was not re-validated was used for the transaction.
    UNVALIDATED_VERSION_USED = 3;

    // The transaction was abandoned and the address was not used.
    UNUSED = 4;
  }

  // Required. The outcome of the sequence of validation attempts.
  //
  // If this field is set to `VALIDATION_CONCLUSION_UNSPECIFIED`, an
  // `INVALID_ARGUMENT` error will be returned.
  ValidationConclusion conclusion = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The ID of the response that this feedback is for. This should be
  // the
  // [response_id][google.maps.addressvalidation.v1.ValidateAddressRequest.response_id]
  // from the first response in a series of address validation attempts.
  string response_id = 2 [(google.api.field_behavior) = REQUIRED];
}

// The response for validation feedback.
//
// The response is empty if the feedback is sent successfully.
message ProvideValidationFeedbackResponse {}

// The result of validating an address.
message ValidationResult {
  // Overall verdict flags
  Verdict verdict = 1;

  // Information about the address itself as opposed to the geocode.
  Address address = 2;

  // Information about the location and place that the address geocoded to.
  Geocode geocode = 3;

  // Other information relevant to deliverability. `metadata` is not guaranteed
  // to be fully populated for every address sent to the Address Validation API.
  AddressMetadata metadata = 4;

  // Extra deliverability flags provided by USPS. Only provided in region `US`
  // and `PR`.
  UspsData usps_data = 5;
}

// High level overview of the address validation result and geocode.
message Verdict {
  // The various granularities that an address or a geocode can have.
  // When used to indicate granularity for an *address*, these values indicate
  // with how fine a granularity the address identifies a mailing destination.
  // For example, an address such as "123 Main Street, Redwood City, CA, 94061"
  // identifies a `PREMISE` while something like "Redwood City, CA, 94061"
  // identifies a `LOCALITY`. However, if we are unable to find a geocode for
  // "123 Main Street" in Redwood City, the geocode returned might be of
  // `LOCALITY` granularity even though the address is more granular.
  enum Granularity {
    // Default value. This value is unused.
    GRANULARITY_UNSPECIFIED = 0;

    // Below-building level result, such as an apartment.
    SUB_PREMISE = 1;

    // Building-level result.
    PREMISE = 2;

    // A geocode that approximates the building-level location of the address.
    PREMISE_PROXIMITY = 3;

    // The address or geocode indicates a block. Only used in regions which
    // have block-level addressing, such as Japan.
    BLOCK = 4;

    // The geocode or address is granular to route, such as a street, road, or
    // highway.
    ROUTE = 5;

    // All other granularities, which are bucketed together since they are not
    // deliverable.
    OTHER = 6;
  }

  // The granularity of the **input** address. This is the result of parsing the
  // input address and does not give any validation signals. For validation
  // signals, refer to `validation_granularity` below.
  //
  // For example, if the input address includes a specific apartment number,
  // then the `input_granularity` here will be `SUB_PREMISE`. If we cannot match
  // the apartment number in the databases or the apartment number is invalid,
  // the `validation_granularity` will likely be `PREMISE` or below.
  Granularity input_granularity = 1;

  // The granularity level that the API can fully **validate** the address to.
  // For example, an `validation_granularity` of `PREMISE` indicates all address
  // components at the level of `PREMISE` or more coarse can be validated.
  //
  // Per address component validation result can be found in
  // [google.maps.addressvalidation.v1.Address.address_components].
  Granularity validation_granularity = 2;

  // Information about the granularity of the
  // [`geocode`][google.maps.addressvalidation.v1.ValidationResult.geocode].
  // This can be understood as the semantic meaning of how coarse or fine the
  // geocoded location is.
  //
  // This can differ from the `validation_granularity` above occasionally. For
  // example, our database might record the existence of an apartment number but
  // do not have a precise location for the apartment within a big apartment
  // complex. In that case, the `validation_granularity` will be `SUB_PREMISE`
  // but the `geocode_granularity` will be `PREMISE`.
  Granularity geocode_granularity = 3;

  // The address is considered complete if there are no unresolved tokens, no
  // unexpected or missing address components. See
  // [`missing_component_types`][google.maps.addressvalidation.v1.Address.missing_component_types],
  // [`unresolved_tokens`][google.maps.addressvalidation.v1.Address.unresolved_tokens]
  // or
  // [`unexpected`][google.maps.addressvalidation.v1.AddressComponent.unexpected]
  // fields for more details.
  bool address_complete = 4;

  // At least one address component cannot be categorized or validated, see
  // [google.maps.addressvalidation.v1.Address.address_components] for
  // details.
  bool has_unconfirmed_components = 5;

  // At least one address component was inferred (added) that wasn't in the
  // input, see
  // [google.maps.addressvalidation.v1.Address.address_components] for
  // details.
  bool has_inferred_components = 6;

  // At least one address component was replaced, see
  // [google.maps.addressvalidation.v1.Address.address_components] for
  // details.
  bool has_replaced_components = 7;
}
