Attach ExposureZone to Customer

  • 1
  • Question
  • Updated 1 month ago
  • (Edited)
Using Java SDK and/or REST (whichever works for the task!)

My goal is, after creating a new customer using Java SDK, I would like to attach an ExposureZone (ie. a state).

I have tried many things, including:

1) adding an ExposureZoneModel to the CustomerModel when creating a customer
            ExposureZoneModel exposureZoneModel = new ExposureZoneModel();
            ArrayList<ExposureZoneModel> aryExposureZones = new ArrayList<ExposureZoneModel>();
//customerModel object already has all address, etc attributes set

I am blindly creating the attributes for the ExposureZoneModel as I can't find docs for guidance.  But that errors with this, which I don't understand I as I am not dealing with a certificate yet.

But that errors with this, which I don't understand I as I am not dealing with a certificate yet. {"error":{"code":"CertificatesError","message":"Certificates API returned error","target":"IncorrectData","details":[{"code":"CertificatesError","number":1203,"message":"Certificates API returned error","description":"{\"success\":false,\"code\":\"20009\",\"error\":\"No data provided for \u0027exposure_zones\u0027.\"}.","faultCode":"Client","helpLink":"","severity":"Error&...}

2) so then I first successfully create the customer.  Then I was trying to find a way to add the exposure.  That is tricky to find.  In the docs I found this URL to post to, where it says adding a Ship-To State will automatically add an ExposureZone:{customerid}/shiptostates

To which I tried to post this json:
{'name':'North Carolina'},{'name':'Washington'}

But I get an error 404 Not Found
I tried this URL as well and get the same 404:{customerid}/shiptostates

BTW, that URL was found in the docs here:

So instead I tried to query an existing account to see what the ExposureZone data looks like in Avatax.  When I use the JavaSDK, I do not get any ExposureZone or Cert info when using client.getCustomer()
ArrayList<ExposureZoneModel> aryExposureZoneModels =  customerModel.getExposureZones();
ArrayList<CertificateModel> aryCertificateModels =  customerModel.getCertificates();

Both of those return null on an account that I can see in the Avatax/CertCapture UI having both certs and exposures.  Further, if I ask for certs on that same customer using:{companyid}/customers/{customerid}/certificates

...I successfully see the certs, and the related ExposureZone.  Why can I see the data with REST, but not the SDK?

1) I am not finding something like client.setExposureZone() for a customer in the JavaSDK
2) I am not finding a functional REST url to use to set a Exposure Zone on a customer record
3) I am getting inconsistent results when querying an existing customer that has ExposureZone values set in avatax
4) I am confused by the vs. url prefixes.  To this point all I have used is and that seems to query things in avatax and CertCapture.  Why and when should I use, if at all?

I'm really not certain what path I should be taking to add an ExposureZone to a customer record.  Advice?


Photo of Robert Mazur

Robert Mazur

  • 9 Posts
  • 0 Reply Likes

Posted 1 month ago

  • 1
Photo of Chris Walker

Chris Walker, Official Rep

  • 25 Posts
  • 2 Reply Likes
Hi Rob,

The reason we have both a CertCapture and Avatax API is not all customers use both products. You are correct that you can query CertCapture using the Avatax API but it does not have the same level of functionality that directly using CertCapture API has, for example there is not an endpoint to directly link an exposure zone in the Avatax API but there is one in the CertCapture API. Below I'll provide examples of how you can achieve your goal using both APIs (also note that you will have different credentials for the CertCapture and Avatax API). The other thing I would like to point out is that you don't want to be creating new exposure zone, you want to be linking existing exposure zones to the customers.

AvaTax API (all of this can be done using the SDK):

Getting a list of exposure zones:
The first thing I would do is call the ListCertificateExpozureZones endpoint This will provide you with a list of exposure zones in an ExposureZoneModel, for example:
      "id": 141,
      "name": "Alabama",
      "tag": "EZ_US_AL",
      "description": "Alabama Sales Tax",
      "region": "AL",
      "country": "US"
We can then use this when creating out customer, you do not need to include every field in the model when creating the customer as they are all optional, I recommend using the "name" field.

Creating a new customer with exposure zones:
For creating our customer we are going to use the CreateCustomers endpoint

    "customerCode": "27c916b3-f10e-4833-8943-8da311f45ebf",
    "alternateId": "987654321",
    "name": "Dr. Bob Example",
    "attnName": "Attn: Receiving",
    "line1": "645 Main Street",
    "city": "Irvine",
    "postalCode": "92614",
    "phoneNumber": "(949) 555-1212",
    "faxNumber": "949.555.1213",
    "emailAddress": "",
    "contactName": "Alice Smith",
    "country": "US",
    "region": "CA",
    "exposureZones": [
        "name": "Washington"
"name": "Alabama"
} ] } ]

Linking exposure zones to an existing customer:
The only way we can link an exposure zone to an existing customer is by using UpdateCustomer . This endpoint does not insert information into an existing customer, it replaces the customer. That means that we will have to send the full CustomerModel again (see above example).

CertCapture API (we do not have an SDK for the CertCapture API):

In the CertCapture API you have to first create the customer, then link the exposure zone. As a side note the CertCapture API references customers by their id and not by the customer_number (which is why you might be getting some errors), If you want to reference customers by their customer number instead make sure you add "x-customer-primary-key: customer_number" to your header.

Create Customer:
You create the customer using the Customers Endpoint

  "id": 1,
  "customer_number": "27xu4u",
  "alternate_id": "01ij2p",
  "name": "Mr. Dangelo Bosco DVM",
  "attn_name": "Madge Schimmel DVM",
  "address_line1": "5278 Breitenberg Plains",
  "address_line2": "",
  "city": "East Geo",
  "zip": "53608",
  "phone_number": "741-872-9685 x3992",
  "fax_number": "657-829-7423 x586",
  "email_address": "",
  "contact_name": "Lucius Bailey",
  "last_transaction": "2011-08-23T21:29:38-0400",
  "country": {
    "name": "US"
  "state": {
    "name": "South Dakota"

Link Exposure Zone:
The easiest way to do this is by using the add Ship-To state


Hopefully this answers your questions, if you want to view examples of the CertCapture API in JAVA in the documentation on the right hand side under requests you can change from raw to any language you like.

Photo of Robert Mazur

Robert Mazur

  • 9 Posts
  • 0 Reply Likes
Thank you for your response, Chris.  I can see I was stuck in the perfect storm of asking the API to do things that it appears to be capable of, but its not.  But using the Avatax REST API with json as you noted above, I was able to accomplish the task.  Thank you.

I am however still having trouble connecting to the CertCapture API.  I am tried everything under the sun,  but I am consistently getting a "HTTP Error code : 401".  I am (for now) trying a simple GET from:

I am aware the CertCapture credentials are different from Avatax, as is the CompanyID is as well.  I am using the credentials I use to log into the CertCapture website via browser.  Is that not what to use?

Also I am using the CompanyID that I see when in CertCapture, I navigate to:
Settings>>Company Settings>>Company Details.  Further, I am adding that CompanyID to the header, like:

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestProperty("Accept", "application/json");
        conn.setRequestProperty("Authorization", token);  //auth token built same way I do for avatax
        conn.setRequestProperty("x-client-id", "{my 6-digit-code}");

Is there something else I should know?

Thank you,

Photo of Katina

Katina, Official Rep

  • 251 Posts
  • 25 Reply Likes

Because the user login credentials force regular changes (and because that would be obnoxious for an integration), REST access to CertCapture actually uses a 2nd password on your account.

To set this password:

  1. Log into CertCapture
  2. Click on your name and go to My Profile
  3. Click REST API Access tab
  4. Add password
  5. Note: the REST username is also case sensitive (so if your username is robmazur, you want to use that and not Robmazur)
For more information, see:

Other than that, it sounds like you're doing everything correct. Please give it a shot and let us know if it works for you (or if you have other problems).
Photo of Robert Mazur

Robert Mazur

  • 9 Posts
  • 0 Reply Likes
Thank you for the reply.  That helped, and I can now perform a GET action in CertCapture.

I am still having trouble with anything requiring POST or PUT.  Specifically, I tried to add a shiptoState to an existing customer.  I used the proper customer id (not my customer number):{the_custid}/shiptostates

...using a POST action.  I receive back:
{"success":false,"code":"30005","error":"Related data not found in request, must be JSON string and one of: [\"ship_to_states\"]"}

OK, that may make sense, because I recognize that perhaps I should instead be using a PUT action.  So I tried that and I get in return:
HTTP Error code : 400
This is what I used:
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.addRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Authorization", token);  //correct auth used in GET
            conn.setRequestProperty("x-client-id", COMPANYID); //correct API ID used in GET       
            String json = "{\"ship_to_states\"=[{ \"name\":\"Washington\"}]}";
            OutputStreamWriter osw = new OutputStreamWriter(conn.getOutputStream());

So instead I try to POST a new customer, which I can successfully do in Avatax.  I use this URL:

I changed and added headers for my clientid, and my auth user/pass (just like for the GET).  I used the exact same JSON content I use in Avatax to create a customer:

        String json =   "{ "+
                "'customerCode': '90000z4',"+
               " 'alternateId': '90000alt4',"+
                "'name': 'Bob Example',"+
                "'attnName': 'Attn: Receiving',"+
                "'line1': '645 Main Street',"+
                "'city': 'Seattle',"+
                "'postalCode': '98101',"+
                "'phoneNumber': '(206) 555-1212',"+
                "'faxNumber': '206.555.1213',"+
                "'emailAddress': '',"+
                "'contactName': 'Alice Smith',"+
                "'country': 'US',"+
                "'region': 'WA',"+
                "'exposureZones': ["+
                    "'name': 'Washington'"+

            StringEntity body = new StringEntity(json);
            HttpResponse response = httpClient.execute(request);

For a result I get:

{"success":false,"code":"10004","error":{"customer_number":["The customer number field is required."]}}

I've tried a few hours of changing headers, and connection methods, etc.  I am continuing to fail on any adding and updating (ie. PUT and POST).  GET works fine.

It gets me wondering, is there something else I need to be doing in CertCapture, maybe a config item, to allow for me to edit data, opposed to a simple GET?


Photo of Robert Mazur

Robert Mazur

  • 9 Posts
  • 0 Reply Likes

I can now successfully PUT and POST some json content (along with my GET actions).  I used brute force to eventually hit the right combo.   See at the bottom for anyone in the future needing an example of using Java to PUT json to the CertCapture API.

What I think helped me most was assuring the Content-Type was correct for the action I was attempting.

For PUT:
HttpPut httpPutRequest = new HttpPut("the_url");
httpPutRequest.addHeader("Content-Type", "application/x-www-form-urlencoded");

HttpPost httpPostRequest = new HttpPost("the_url");
httpPostRequest.addHeader("Content-Type", "application/json");


For anyone in the future trying to PUT some json to the CertCapture API, this worked for me.  Hope this helps.

    public void putShiptoState() { 

        String result = null;
        String postUrl = "{use_your_custid}/shiptostates";
        // USERNAME and PASSWORD set as Strings above
        String token = "Basic "+Base64.getEncoder().encodeToString((USERNAME + ":" + PASSWORD).getBytes());

        java.lang.System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpPut httpPutRequest = new HttpPut(postUrl);
        httpPutRequest.addHeader("Authorization", token);
        httpPutRequest.addHeader("x-client-id", COMPANYID);  //set as a String above
        httpPutRequest.addHeader("Content-Type", "application/x-www-form-urlencoded");
        try {
            String json = "ship_to_states=[{\"name\":\"Indiana\"}]";
            StringEntity body = new StringEntity(json);

            System.out.println("Here is the request URL:\n " + httpPutRequest.toString());

            HttpResponse response = httpClient.execute(httpPutRequest);
            System.out.println("request posted, response received. response code "+response.getStatusLine().getStatusCode());
            System.out.println("response: " + response.toString());
            result = EntityUtils.toString(response.getEntity(), "UTF-8");
            System.out.println("request posted, response received, client closed");
        } catch (Exception e) {
        System.out.print("Here is the result:\n " + result);