A person types "Charlotte" into a city field and chooses a result. The form saves the word. When they return, the application searches for Charlotte again and picks the first match.
That second search is a new decision. It may have different country context, a different ranking, or an updated set of records. The application had a specific choice and reduced it to a search term.
A useful place model keeps three things separate: what someone entered, which place they selected, and the label shown on screen. That separation makes an international form easier to edit and a saved record easier to understand later.
Save the identity and its scope
A name is useful for finding a place. A code or ID is useful for referring to it again. The scope belongs with the code: CA alone does not tell you whether the value represents a country or a state inside one.
For the ParseAPI place endpoints, these are the useful storage boundaries:
| Place | Keep for identity | Keep for display |
|---|---|---|
| Country | country, the ISO2 code | name |
| State or province | country and state together | name |
| District | country and district together; retain state as context | name |
| City | The returned id, plus country and state context | name |
| Postal code | country and the returned postal string | Its available locality and administrative names |
These are fields from the corresponding endpoint, not one combined response. On a city response, for example, the state's display label is state_name; the city's own label is name.
Country codes scope subdivision codes. MP is two places shows why a state code needs its country. District codes can also collide across countries. Even when a bare code happens to resolve today, saving the country removes a dependency on uniqueness across the rest of the catalog.
City names need another step. The exact-name endpoint can choose the largest population when names tie. For a person making a choice, use the city search results, show enough context to distinguish them, and save the selected result's id.
This request example uses the API 2.0.0 contract:
GET /city?q=char&country=US&state=NC HTTP/1.1
Host: api.parseapi.com
X-API-Key: YOUR_API_KEY
Parse-Version: 2.0.0
The response contains a cities array. Each result has its own identity and labels. Fetch a saved choice through /city/id/{id} instead of repeating its name search. A city you can pin walks through that distinction.
Treat the ID as opaque. Do not derive meaning from its characters, manufacture one from a name, or replace a missing ID with a coordinate pair. If a selected result lacks an ID, keep it unresolved in your own model rather than pretending you saved a durable reference.
Let labels change without changing the selection
A display name can have an accent, a native form, a romanized form, or a translation chosen by your application. None of those choices should change the stored country code or city ID.
Country, State and City expose a nullable name_local for a native name. A native name is not necessarily a translation into the reader's preferred language. In the default response, a missing native name or one identical to the primary name is returned as null.
When a native label is appropriate for the interface, the fallback is small:
const label = place.name_local ?? place.name;
Handle an absent primary name too: show another available label or an explicit placeholder. Do not turn null into the visible word "null", an empty option, or a fabricated name.
Postal responses use city_local, state_name_local and district_name_local alongside their primary labels. They do not use name_local for the whole postal record. The native-name explanation covers this pairing.
A label snapshot can still be worth saving. It lets an application explain what someone selected at the time, even if a later display name changes. Use the ID or scoped code to join records; use the snapshot to explain the old screen. Give those fields different names so the next developer can see the difference.
Postal codes stay strings
Postal codes are identifiers even when every character happens to be a digit. Converting 00901 to a number loses information. A model that only accepts digits also cannot represent SW1A 1AA.
Keep the original text separately from the lookup's returned postal value, and keep the country with both. Normalization can change spacing or punctuation. The Postal API also resolves a US ZIP+4 to its five-digit ZIP for the lookup. That shorter result should not silently replace the full code someone entered for their address.
The same care applies to imports and exports. A JSON string can become a number when a spreadsheet opens a CSV. Declare postal and subdivision-code columns as text when importing them; quoting a CSV cell alone does not guarantee the receiving application will preserve its type.
A postal lookup may supply a locality name without a city ID. Do not join it to a City record by matching that label alone. Keep the postal association, or perform a separate selection with the available country and state context.
Editing a parent changes the question
A city suggestion belongs to the country, state and query that produced it. Selecting another country makes the old suggestion list stale, even if the text in the city box has not changed.
When a country changes, invalidate the dependent state, district and city selections and request fresh options. When a state changes, do the same for its dependent selections. Retain useful typed text if the interface allows it, but clear the old saved identity until the person makes a valid new choice.
Async requests need the same boundary. Only apply a response if its country, state and query still match the current form. A slow response for the previous country must not repopulate a dropdown after the person has moved on. Cancelling old requests helps; checking the context before applying a result protects the state itself.
Editing the city text after a selection should also clear the selected ID. Otherwise the screen can say one city while the hidden value submits another. A selected option and free text are different states, and the submit handler needs to know which one it has.
Do not make every administrative level mandatory. A returned district or state may be null. Ask for the location detail the workflow needs, and let the model represent an unknown or unavailable value without substituting 0 or an empty string.
Keep coordinates and provenance in their own fields
Coordinates describe a position associated with a record. They do not give it a durable identity. Postal coordinates are approximate and can be unavailable; two records sharing a point are not necessarily duplicates.
There is also a difference between a point's administrative location and its nearest city. Point resolves country, state and district at the supplied coordinates. Its optional nearest-city context is a separate association. A nearby city should not overwrite a city the person explicitly selected.
Here is an illustrative application record using the documented Charlotte ID. These are application field names, not an API response:
{
"entered_city": "char",
"country": "US",
"state": "NC",
"city_id": "city_mb8mbqrkz8zb",
"city_label_at_selection": "Charlotte",
"selection_method": "city_picker",
"api_version": "2.0.0"
}
The raw entry explains the search. The ID records the choice. The label explains what the person saw. Recording the lookup time and response version alongside that choice can help diagnose a later difference without rerunning the search and assuming it reproduces the past.
Store only the provenance your workflow needs, under the same retention rules as the rest of the record. When the place is loaded again, resolve the saved identity, refresh the display label if appropriate, and leave the original choice understandable.