Verifying addresses

A friend has a Dymo address labeler. He says its software can verify addresses. I don’t know if he means it attaches names to addresses or only confirms that the address exists - probably just that as many names can be associated with one address.

Panorama has its Zip code lookup for City/State. Has anyone extended that, probably with something like AppleScript, to verify addresses? I think DYMO was using a free post office service. They let their customers know that the Gov’t may start charging them for the service.

I’m just wondering how, if anyone has extended their mailing list management, they interfaced with that service?

Checkout ZipInfoPlus(

I’m gunna bet against the Post Office from starting to charge for this service as it benefits them more than its customers.

Thank you Robert. That’s pretty cool if it works. But the Help file seems a bit lacking. In the Parameters description it mentions “zipplusinfo - … (see discussion below)” but never mentions that variable again.

Also, it isn’t clear if the zip field is numeric or alpha. It might be numeric as the Zip9 would be something like 977022321 instead of 97702-2321.

I didn’t see any words discussing initializing of a dictionary.

I copied the sample procedure, adding

Local Address, City, State, Zip, zinfo

and filling the Address, City, State (2 characters), and zip (5 digits). First I tried Zip as text (“97702”) then as numeric (97702), then just using ““.

After filling the Address, City, State, Zip with data, I ran the procedure with my address, city, state and the three different zip designations. Each time it returned not valid.

Is the dictionary initialization missing from the example? Is zipplusinfo just a dyslexic zipinfoplus, or is zipplusinfo meant to be what is then called zinfo?

Adding a working example, maybe using the address of Apple Headquarters or some public edifice, to the documentation would be helpful.

USPS has changed their web page, and I was using an API from ZIP-Codes.com to access the USPS API, because I am not great at using this stuff. Then USPS changed their API, and ZIP-Codes.com has just changed theirs, and I have not had the chance to test ouf how either of those work. I looked at the ZIP-Codes.com info, and their developer sent an email saying that he saw that I looked at it, and asked why I had not used it. I just sent a reply that explained basically what was going on, along with the Panorama code I had been using, so maybe he will explain what I need to do. To use it, you need a key, which I had, but of course, I did not want to post it with my key, and I never got around to adding code to look for the key, which should be a permanent variable, and asking you to go get one if you do not have one.

I think the USPS API may be simpler now, but then, I am pretty simple myself! The USPS service is free, and the ZIP-Codes is free for like 2500 lookups a day, which is more than adequate for my usage.

Anyway, if anyone wants to try to get it to work, this is my code:

local vAddress1, vAddress2, vCity, vState, vZip, vQuery, rAddress1, rAddress2, rCity, rState, rZip5, rZip4, rError, rDictionary, APIKey

APIKey = “####################"

vAddress1=encodeurlquery(Parameter(1))
vAddress2=encodeurlquery(Parameter(2))
vCity=encodeurlquery(Parameter(3))
vState=encodeurlquery(Parameter(4))
vZip=encodeurlquery(Parameter(5)[1,5])

loadurl vQuery, “https://api.zip-codes.com/ZipCodesAPI.svc/1.0/ZipCodeOfAddress?address=” + vAddress1 + “&address1=” + vAddress2 + “&city=” + vCity + “&state=”+vState+“&zipcode=”+vZip+“&key=”+APIKey

rAddress1=tagdata(vQuery,‘Address2": “’,‘”,’,1)
rAddress2=tagdata(vQuery,‘Address1": “’,‘”,’,1)
rCity=tagdata(vQuery,‘City": “’,‘”,’,1)
rState=tagdata(vQuery,‘State": “’,‘”,’,1)
rZip5=tagdata(vQuery,‘Zip5": “’,‘”,’,1)
rZip4=tagdata(vQuery,‘Zip4": “’,‘”’,1)
rError=tagdata(vQuery,’ “Error”: “‘,’”',1)

rDictionary=“”

setdictionaryvalue rDictionary,“ADDRESS”,rAddress1+rAddress2
setdictionaryvalue rDictionary,“CITY”,rCity
setdictionaryvalue rDictionary,“STATE”,rState
setdictionaryvalue rDictionary,“ZIP9”,rZip5+“-”+rZip4
setdictionaryvalue rDictionary,“ERROR”,rError

//displaydata dumpdictionary(rDictionary)

setparameter 6,rDictionary

I took a quick look at the zip-codes.com documentation. They are using JSON for the responses, so I would recommend using Panorama’s JSON parsing instead of trying to parse it with tagdata(.

First, use the jsonimport( function to bring the data into a variable as a data dictionary.

Then you can use the getstructurevalue( function to easily extract any value you want from the variable.

Actually, the problem is the syntax to make the request. I think I can figure it out after that. That has always been my sticking point. I am not versed in computer languages so much. I have not followed how the languages have changed over the years.

I got a response from their developer, but it is in JavaScript:

const address = “1600 Pennsylvania Ave NW, Washington DC”; // street address to validate
const apiKey = “YOUR_API_KEY”;

const url = “https://api.zip-codes.com/v2/address?”

  • “address=” + encodeURIComponent(address);

const resp = await fetch(url, {
headers: { “X-API-Key”: apiKey }
});
const data = await resp.json();
console.log(JSON.stringify(data, null, 2));

It will return the address with ZIP+4 and other fields in a structured manner.

The zip-codes.com documentation is here:

This documentation includes examples using curl, which is basically the same as Panorama’s url( or loadurl( function. Here is their example to use curl to look up an address in New York.

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://api.zip-codes.com/v2/address?address=350+5th+Ave%2C+New+York+NY+10118"

The Panorama equivalent would be:

let jsonResult =
  url("https://api.zip-codes.com/v2/address?address=350+5th+Ave%2C+New+York+NY+10118&key=YOUR_API_KEY")

Note that in the address spaces have been converted to + characters, and commas have been converted into %2C. I’m not sure why, that is not standard URL encoding, but you can convert plain data into this format using the replace( function.

replace("hello, world"," ","+",",","%2C")

Suppose you have a database with Address, City, State and Zip fields. You could look up the current record with this code.

let jsonResult =
  url("https://api.zip-codes.com/v2/address?"+
    "address="+replace(Address," ","+",",","%2C")+"%2C"+
    "&city="+replace(City," ","+")+"+"+
    "&state="+State+"+"+
    "&zip="+Zip+"+"+
    "&key=YOUR_API_KEY")

Note that I am assuming that the City field doesn’t contain commas, and the State and Zip field don’t contain commas or spaces. Also note that I haven’t tested this code, but it should be pretty close.

Once you have the json result, you can use jsonimport( and getstructurevalue( to extract whatever components of the result you want.

Bruce, Please say a little more about the API Key. Is there a fee? And what is returned - for example if you used Jim’s json procedure - if the address is invalid?

Okay, Jim, I will work on it when I get some time. I am in negotiations with the Musicians Union, as well as a payroll service for the city’s band, and that is using up both a lot of my time and brain power.

I might be able to do it with the USPS API, which is free, but Zip-Codes.com, like I said, is free for up to 2500 inquiries a day and does Canada, I believe, which is well beyond my needs. For more information about what they do and what they charge, you can read about it on their website.

Programming is just a hobby for me. I do not do much unless there is a real need. zipinfoplus is very convenient, enough so that I maintained it for a long time, but there have been other things in my life that have taken precedence. I will try to get it to work again, but I have a lot to do before the July 4 start of the band season.