Table of Contents

FedEx® Integration

AddressValidation offers a complete integration to the FedEx® Address Validation API to provide validation for 46 countries.

Credentials

Get a developer account with FedEx before you use this integration. After you sign in, follow these instructions to get your credentials.

Installation

The easiest way to install the integration into a project is through NuGet:

dotnet package add VisusIO.AddressValidation.Integration.FedEx

Register the integration with the Microsoft DI container at application startup:

builder.Services.AddFedExAddressValidation();
Important

HybridCache caches access tokens. See the Caching section for details.

Configuration

Configuration is bound from the AddressValidationSettings:FedEx section.

{
  "AddressValidationSettings": {
    "FedEx": {
      "AccountNumber": "<your account number>",
      "ClientId": "<your client id>",
      "ClientSecret": "<your client secret>",
      "ClientEnvironment": "PRODUCTION"
    }
  }
}
Property Required Description
AccountNumber Yes Your FedEx account number
ClientId Yes OAuth 2.0 client ID issued by FedEx for your registered application
ClientSecret Yes OAuth 2.0 client secret issued by FedEx for your registered application
ClientEnvironment No Accepted values: PRODUCTION, DEVELOPMENT, SANDBOX. Defaults to DEVELOPMENT
Locale No IETF BCP 47 language tag for the response locale (e.g., en-US). When omitted, FedEx uses its default locale.
EndpointUriOverride SANDBOX only Custom endpoint URI; required when ClientEnvironment is SANDBOX
Important

Store ClientId and ClientSecret encrypted at rest. See Security for more details.

Standard Example

The following example demonstrates a standard address validation request.

public class ValidateController
{
    private readonly IAddressValidationService<FedExAddressValidationRequest> _validationService;

    public ValidateController(IAddressValidationService<FedExAddressValidationRequest> validationService)
    {
        _validationService = validationService ?? throw new ArgumentNullException(nameof(validationService));
    }

    [HttpPost]
    public async Task<IActionResult> Post([FromBody] FedExAddressValidationRequest request, CancellationToken cancellationToken = default)
    {
        IAddressValidationResponse? response = await _validationService.ValidateAsync(request, cancellationToken);

        return response is null
            ? new NotFoundResult()
            : response.Errors.Count > 0
                ? new UnprocessableEntityObjectResult(response)
                : new OkObjectResult(response);
    }
}
{
  "addressesToValidate": [
    {
      "address": {
        "streetLines": [
          "1000 5th Ave"
        ],
        "city": "New York",
        "stateOrProvince": "NY",
        "postalCode": "10028",
        "countryCode": "US"
      }
    }
  ]
}
Note

transactionId is always present in customResponseData. When you set CustomerTransactionId on the request, customerTransactionId is also present, with the same value the FedEx API echoes back.

Note

The Suggestions collection is always empty. The FedEx® Address Validation API does not provide address suggestions.

Warning

Treat the returned isResidential value as a suggestion, not a guarantee.

Note

AddressValidation runs an internal validation engine under the covers to validate both the request and the response. These results appear in the Warnings and Errors collections on the IAddressValidationResponse object.

The internal validator does not process items in the Suggestions collection.

Batch Example

FedEx® is currently the only integration that supports validating multiple addresses in a single call. Inject IBatchAddressValidationService<FedExAddressValidationRequest> and call ValidateManyAsync with up to 100 requests.

public class ValidateController
{
    private readonly IBatchAddressValidationService<FedExAddressValidationRequest> _batchValidationService;

    public ValidateController(IBatchAddressValidationService<FedExAddressValidationRequest> batchValidationService)
    {
        _batchValidationService = batchValidationService ?? throw new ArgumentNullException(nameof(batchValidationService));
    }

    [HttpPost]
    public async Task<IActionResult> Post([FromBody] IReadOnlyList<FedExAddressValidationRequest> requests, CancellationToken cancellationToken = default)
    {
        IReadOnlyList<IAddressValidationResponse?> responses = await _batchValidationService.ValidateManyAsync(requests, cancellationToken);

        return new OkObjectResult(responses);
    }
}
Note

ValidateManyAsync returns one entry per request, in the same order you submitted the requests. An entry is an EmptyAddressValidationResponse when the request failed local validation, or when FedEx could not resolve it. An entry is null only when the entire batch call produced no response. Each result carries a per-item outcome, instead of one status for the whole call — inspect each entry instead of the HTTP status code.

{
  "addressesToValidate": [
    {
      "address": {
        "streetLines": [
          "7372 Parkridge Blvd",
          "Apt 286"
        ],
        "city": "Irving",
        "stateOrProvince": "TX",
        "postalCode": "75063",
        "countryCode": "US"
      }
    },
    {
      "address": {
        "streetLines": [
          "1600 Pennsylvania Ave NW"
        ],
        "city": "Washington",
        "stateOrProvince": "DC",
        "postalCode": "20500",
        "countryCode": "US"
      }
    }
  ]
}
Note

customResponseData is populated on each entry the same way as the Standard Example; it is omitted above to keep the example readable.

Note

A batch is limited to 100 addresses. Submitting more throws an ArgumentException before any request reaches FedEx.

Note

FedEx accepts only one transaction identifier per batch call, so CustomerTransactionId set on any request other than the first in the batch is not transmitted.

Note

FedEx's resolve endpoint does not echo clientReferenceId (or any other per-item identifier) back on a resolved address. This library correlates results to requests strictly by list position, not by any field in the response. clientReferenceId is still sent to FedEx for its own tracking, but it has no effect on how this library matches a response to its request.

Warning

Treat the returned isResidential value as a suggestion, not a guarantee.

Note

AddressValidation runs an internal validation engine under the covers to validate both the request and the response. These results appear in the Warnings and Errors collections on the IAddressValidationResponse object.

The internal validator does not process items in the Suggestions collection.