parseapi 1.9.3 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +53 -6
- data/lib/parseapi/client.rb +71 -20
- data/lib/parseapi/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 990610f93533ebcd100f77004d702eba941f0631f1c87c18922728bb75766892
|
|
4
|
+
data.tar.gz: 7065ef9890901017612552b7654e1976eb6b84d79ef18f0415be3f50a6e30d61
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 74bf7c89388ab944f78c737576956287e5449e142dde81527c5a6bad16f3b90088084392d8fc67f2bfbdd256308e3d56364e104641ca8d9ebc13fc9a5b103fd0
|
|
7
|
+
data.tar.gz: 1e0ce68699e0dabfe86ff35e16a80ff9470cadcd582d3a4b5586105c91ad0384353fc84fdef8218d15578d812c792de1243d1ec9302f209e1cd949802fd02bf1
|
data/README.md
CHANGED
|
@@ -141,7 +141,6 @@ parse.mx('example.com')
|
|
|
141
141
|
parse.dns('example.com')
|
|
142
142
|
parse.dns('_dmarc.example.com', type: 'TXT')
|
|
143
143
|
parse.useragent(ua_string)
|
|
144
|
-
parse.vehicle('1HGCM82633A004352')
|
|
145
144
|
parse.industry('541511')
|
|
146
145
|
parse.industry_search('coffee shop', limit: 5)
|
|
147
146
|
parse.tariff('8471.30.01.00', origin: 'CN', deep: true)
|
|
@@ -243,7 +242,7 @@ place = parse.postal('28202', country: 'US', deep: true)
|
|
|
243
242
|
property_tax = place.dig('deep', 'property_tax')
|
|
244
243
|
```
|
|
245
244
|
|
|
246
|
-
Read `
|
|
245
|
+
Read `population` as the source’s count for that place boundary. Keep missing or null values unknown and preserve a known zero. State district lists include each district’s population. Postal nearby and distance detail remains metropolitan associations only. Continent population stays in core.
|
|
247
246
|
|
|
248
247
|
Country deep includes `land_area` and `water_area` in km2, `coastline` in km, and mean `elevation` in metres. `lowest_point` and `highest_point` contain a nullable `name` and an `elevation` in metres. Values below sea level are negative. Missing or null values stay unknown, and zero stays zero.
|
|
249
248
|
|
|
@@ -297,7 +296,7 @@ Invalid input returns `valid: false` with unknown provider fields. A checksum-va
|
|
|
297
296
|
|
|
298
297
|
The default pooled lookup includes provider identity, specialty and practice contact where held. Paid `deep` adds `deactivated_at`, `medicare`, `opt_out` and `enrollments` from stored source files, with no separate check meter or live verification. `enrollments: null` means unavailable; `[]` means no enrollment rows are returned. The API omits unrequested `deep` and returns `{}` when requested on Free.
|
|
299
298
|
|
|
300
|
-
Paid Deep also returns `taxonomies` in published order, with taxonomy code, specialty label, primary flag and provider-reported license number/state, plus `enumerated_at`, `updated_at` and `reactivated_at` record dates. Reported licenses are not verified licenses. Null lists mean unavailable; empty lists mean the edition contains no entries.
|
|
299
|
+
Paid Deep also returns `taxonomies` in published order, with taxonomy code, specialty label, primary flag and provider-reported license number/state, plus `enumerated_at`, `updated_at` and `reactivated_at` record dates. Reported licenses are not verified licenses. Null lists mean unavailable; empty lists mean the edition contains no entries. Provider record dates describe the provider record. Unknown dates stay null.
|
|
301
300
|
|
|
302
301
|
## Deep
|
|
303
302
|
|
|
@@ -313,7 +312,7 @@ Choose enrichment for the question you need answered.
|
|
|
313
312
|
| Country, State, District, City, Postal | The place profile on paid plans, including demographic and tax facts where held. |
|
|
314
313
|
| Name, Industry | Name evidence or the industry definition profile on paid plans. |
|
|
315
314
|
| NPI | Deactivation date, Medicare enrollment, opt-out and enrollment rows from stored sources on paid plans. Exclusion evidence stays core. |
|
|
316
|
-
|
|
|
315
|
+
| Tariff, Company | The complete product detail bag on paid plans. |
|
|
317
316
|
| Weather | Specialist current measurements and the existing forecast, alert, air and history bag on paid plans. |
|
|
318
317
|
| Carrier, HLR | Optional diagnostic detail within the same metered core unit, including Free allowance units. No second gate or additional check. |
|
|
319
318
|
|
|
@@ -420,8 +419,6 @@ Successful checks may be reused for up to 24 hours. `pretty` optionally formats
|
|
|
420
419
|
|
|
421
420
|
Stack defaults to a 35-second transport timeout so a first scan has time to finish. Other lookups retain their 10-second default. An explicit client timeout takes precedence.
|
|
422
421
|
|
|
423
|
-
Vehicle lookups use `vin` as the input and response field. Existing VIN methods remain available for compatibility.
|
|
424
|
-
|
|
425
422
|
## Emoji catalog additions
|
|
426
423
|
|
|
427
424
|
Resolve Unicode emoji or a named shortcode, search or browse a bounded catalog,
|
|
@@ -453,3 +450,53 @@ A device's emoji font remains the ordinary display.
|
|
|
453
450
|
|
|
454
451
|
These additions are a local release candidate until the matching SDK and
|
|
455
452
|
backend are published. Existing lookup and search contracts are preserved.
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
## City collections
|
|
456
|
+
|
|
457
|
+
```ruby
|
|
458
|
+
page = parse.city_list(country: 'JP', min_population: 100_000, sort: 'population', limit: 20)
|
|
459
|
+
nearby = parse.city_nearby_coords(34.57, 135.48, radius: 20, unit: 'km', country: 'JP')
|
|
460
|
+
search = parse.city_search('Sak', page: true)
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Browse the curated City catalog or list cities around a supplied coordinate. These operations return `next_cursor`, which is null at the end. Treat it as opaque and reuse all filters, limit, language, hierarchy and deep settings for the next page. Existing name searches and named nearby calls include pagination metadata only when paging or a cursor is requested.
|
|
464
|
+
|
|
465
|
+
Collection options include minimum and maximum population, an exact IANA timezone, and `bbox` in `west,south,east,north` order. A west bound greater than east crosses the dateline. Population filtering and sorting use the same count as paid Deep: an admitted observation when available, otherwise the stored count. Missing counts do not match a population range and sort last; legacy counts keep unknown dates. Coverage and observation dates vary by place.
|
|
466
|
+
|
|
467
|
+
Collections support `name`, `population`, `country` and `elevation`; search also supports `relevance`, and nearby supports `distance`. Combine up to three signed terms, for example `sort=-population,name`. A signed multi-key sort does not also take `order`. Population defaults to descending order; other sorts default to ascending. Set `order` to `asc` or `desc`, except relevance only supports ascending. Named nearby uses country and state to select the anchor; population, timezone and bounding box filter the returned neighbors. Coordinate nearby applies country and state to its returned cities.
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
## Canonical City operations
|
|
472
|
+
|
|
473
|
+
Classic lookup, search, nearest and named-nearby methods retain their default envelopes and required-field models. Browse and coordinate-nearby use canonical lists: `object`, `data` and nullable `next_cursor` (camelCase properties in Swift/Kotlin). Keep all query options unchanged when continuing a page; no client fetches pages automatically.
|
|
474
|
+
|
|
475
|
+
```ruby
|
|
476
|
+
page = parse.city_search('Viena', format: 'list', match: 'fuzzy', max_distance: 1)
|
|
477
|
+
children = parse.city_children('city_7aj899nvwyku')
|
|
478
|
+
distance = parse.city_distance('city_7aj899nvwyku', 'city_7aj899nvwyku')
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
Select `format=resource` for one City or `format=list` for a collection. Country inclusion/exclusion sets, timezone sets, inclusive population and meter-elevation bounds, stored-center `bbox` and signed multi-key sorting are available for collections. Unknown numeric facts do not match range filters.
|
|
482
|
+
|
|
483
|
+
Search defaults to prefix matching. Exact and fuzzy matching are explicit; fuzzy accepts maximum edit distance 1 or 2 and returns `match` evidence (`type`, `source`, `value`, `language`, `edit_distance`). Review a fuzzy choice before storing its ID.
|
|
484
|
+
|
|
485
|
+
Reviewed children, ancestors and siblings use canonical lists with partial relationship coverage. Empty data does not prove there are no geographic relatives. Children/siblings accept page controls; ancestors do not. Distance reports great-circle kilometers and miles between stored centers: zero is known zero, null is unknown, and it does not imply travel time or containment.
|
|
486
|
+
|
|
487
|
+
Strict `ambiguity=error` can return HTTP 409 `ambiguous_city` with up to two safe candidate identities. The existing error constructor and unrelated error metadata are preserved; candidates are retained only for that status/code and never contain Deep. GeoJSON is available through HTTP; these typed City list methods do not return GeoJSON.
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
Reviewed name forms:
|
|
492
|
+
|
|
493
|
+
```ruby
|
|
494
|
+
city = parse.city_id('city_7aj899nvwyku', format: 'resource', romanized: true)
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
Coverage by country and available fields is described at https://parseapi.com/city#coverage.
|
|
498
|
+
|
|
499
|
+
`romanized=true` requests reviewed official name forms as `name_romanized` and `romanization_language` (camelCase in Swift/Kotlin). Current reviewed forms cover 20 Japanese whole-city aliases in ja-Latn. Missing or conflicting forms stay null; ASCII folding is not substituted for an official form.
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
Conditional `If-None-Match` reads and GeoJSON currently use HTTP directly. A matching City ETag returns 304 without a body; ordinary billing and rate limits apply. These JSON client methods do not supply conditional-cache handling.
|
data/lib/parseapi/client.rb
CHANGED
|
@@ -6,7 +6,7 @@ require 'time'
|
|
|
6
6
|
module ParseAPI
|
|
7
7
|
# Every non-2xx response from the API. Branch on +code+, never on the message.
|
|
8
8
|
class Error < StandardError
|
|
9
|
-
attr_reader :status, :code, :docs, :request_id, :retry_after
|
|
9
|
+
attr_reader :status, :code, :docs, :request_id, :retry_after, :candidates
|
|
10
10
|
|
|
11
11
|
def initialize(status:, code:, message:, docs: nil, request_id: nil, retry_after: nil)
|
|
12
12
|
super(message)
|
|
@@ -106,28 +106,69 @@ module ParseAPI
|
|
|
106
106
|
get("/district/#{seg(code)}", country: country, state: state, deep: deep, lang: lang)
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
def city(name, country: nil, state: nil, deep: false, lang: nil)
|
|
110
|
-
get("/city/#{seg(name)}", country: country, state: state, deep: deep, lang: lang)
|
|
109
|
+
def city(name, country: nil, state: nil, deep: false, lang: nil, type: nil, grain: nil, hierarchy: false, aliases: false, ambiguity: nil, format: nil, romanized: false)
|
|
110
|
+
get("/city/#{seg(name)}", country: country, state: state, deep: deep, lang: lang, type: type, grain: grain, hierarchy: hierarchy, aliases: aliases, ambiguity: ambiguity, romanized: romanized, format: format)
|
|
111
111
|
end
|
|
112
112
|
|
|
113
|
-
def city_id(id, deep: false, lang: nil)
|
|
114
|
-
get("/city/id/#{seg(id)}", deep: deep, lang: lang)
|
|
113
|
+
def city_id(id, deep: false, lang: nil, hierarchy: false, format: nil, romanized: false)
|
|
114
|
+
get("/city/id/#{seg(id)}", deep: deep, lang: lang, hierarchy: hierarchy, romanized: romanized, format: format)
|
|
115
115
|
end
|
|
116
116
|
|
|
117
|
-
def city_search(query, country: nil, state: nil, limit: nil, deep: false, lang: nil)
|
|
118
|
-
|
|
117
|
+
def city_search(query, country: nil, state: nil, limit: nil, deep: false, lang: nil, type: nil, grain: nil, hierarchy: false, aliases: false, min_population: nil, max_population: nil, timezone: nil, bbox: nil, sort: nil, order: nil, page: false, cursor: nil, format: nil, countries: nil, exclude_countries: nil, timezones: nil, min_elevation: nil, max_elevation: nil, match: nil, max_distance: nil, romanized: false)
|
|
118
|
+
spelling = !match.nil? || !max_distance.nil?
|
|
119
|
+
response = get(spelling ? '/city/search' : '/city', q: query, match: match, max_distance: max_distance, country: country, state: state, limit: limit, deep: deep, lang: lang, type: type, grain: grain, hierarchy: hierarchy, aliases: aliases, min_population: min_population, max_population: max_population, timezone: timezone, bbox: bbox, sort: sort, order: order, page: page, cursor: cursor, romanized: romanized, format: format, countries: city_csv(countries), exclude_countries: city_csv(exclude_countries), timezones: city_csv(timezones), min_elevation: min_elevation, max_elevation: max_elevation)
|
|
120
|
+
if spelling && format.nil?
|
|
121
|
+
classic = {"q"=>query, "cities"=>response.fetch("data"), "next_cursor"=>response["next_cursor"]}
|
|
122
|
+
classic["country"] = country unless country.nil?
|
|
123
|
+
classic["state"] = state unless state.nil?
|
|
124
|
+
return classic
|
|
125
|
+
end
|
|
126
|
+
response
|
|
119
127
|
end
|
|
120
128
|
|
|
121
|
-
def city_nearest(lat, lon, deep: false, lang: nil)
|
|
122
|
-
get('/city', lat: lat, lon: lon, deep: deep, lang: lang)
|
|
129
|
+
def city_nearest(lat, lon, deep: false, lang: nil, country: nil, state: nil, type: nil, grain: nil, hierarchy: false, format: nil, romanized: false)
|
|
130
|
+
get('/city', lat: lat, lon: lon, deep: deep, lang: lang, country: country, state: state, type: type, grain: grain, hierarchy: hierarchy, romanized: romanized, format: format)
|
|
123
131
|
end
|
|
124
132
|
|
|
125
|
-
def city_nearby(name, radius: nil, unit: nil, country: nil, state: nil, limit: nil, deep: false, lang: nil)
|
|
126
|
-
get("/city/#{seg(name)}/nearby", radius: radius, unit: unit, country: country, state: state, limit: limit, deep: deep, lang: lang)
|
|
133
|
+
def city_nearby(name, radius: nil, unit: nil, country: nil, state: nil, limit: nil, deep: false, lang: nil, type: nil, grain: nil, hierarchy: false, aliases: false, ambiguity: nil, min_population: nil, max_population: nil, timezone: nil, bbox: nil, sort: nil, order: nil, page: false, cursor: nil, format: nil, countries: nil, exclude_countries: nil, timezones: nil, min_elevation: nil, max_elevation: nil, romanized: false)
|
|
134
|
+
get("/city/#{seg(name)}/nearby", radius: radius, unit: unit, country: country, state: state, limit: limit, deep: deep, lang: lang, type: type, grain: grain, hierarchy: hierarchy, aliases: aliases, ambiguity: ambiguity, min_population: min_population, max_population: max_population, timezone: timezone, bbox: bbox, sort: sort, order: order, page: page, cursor: cursor, romanized: romanized, format: format, countries: city_csv(countries), exclude_countries: city_csv(exclude_countries), timezones: city_csv(timezones), min_elevation: min_elevation, max_elevation: max_elevation)
|
|
127
135
|
end
|
|
128
136
|
|
|
129
137
|
# Look up a postal area. Pass country when known. Check nullable coordinates before another
|
|
130
138
|
# location lookup.
|
|
139
|
+
def city_ancestors(id, hierarchy: false, deep: false, lang: nil, romanized: false)
|
|
140
|
+
get("/city/id/#{seg(id)}/ancestors", romanized: romanized, hierarchy: hierarchy, deep: deep, lang: lang)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def city_children(id, limit: nil, cursor: nil, hierarchy: false, deep: false, lang: nil, romanized: false)
|
|
147
|
+
get("/city/id/#{seg(id)}/children", limit: limit, cursor: cursor, romanized: romanized, hierarchy: hierarchy, deep: deep, lang: lang)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def city_distance(from, to)
|
|
153
|
+
get("/city/id/#{seg(from)}/distance/#{seg(to)}")
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def city_list(country: nil, state: nil, limit: nil, deep: false, lang: nil, type: nil, grain: nil, hierarchy: false, min_population: nil, max_population: nil, timezone: nil, bbox: nil, sort: nil, order: nil, cursor: nil, countries: nil, exclude_countries: nil, timezones: nil, min_elevation: nil, max_elevation: nil, romanized: false)
|
|
158
|
+
get('/city', browse: true, country: country, state: state, limit: limit, deep: deep, lang: lang, type: type, grain: grain, hierarchy: hierarchy, min_population: min_population, max_population: max_population, timezone: timezone, bbox: bbox, sort: sort, order: order, cursor: cursor, romanized: romanized, format: 'list', countries: city_csv(countries), exclude_countries: city_csv(exclude_countries), timezones: city_csv(timezones), min_elevation: min_elevation, max_elevation: max_elevation)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def city_nearby_coords(lat, lon, radius: nil, unit: nil, country: nil, state: nil, limit: nil, deep: false, lang: nil, type: nil, grain: nil, hierarchy: false, min_population: nil, max_population: nil, timezone: nil, bbox: nil, sort: nil, order: nil, cursor: nil, countries: nil, exclude_countries: nil, timezones: nil, min_elevation: nil, max_elevation: nil, romanized: false)
|
|
163
|
+
get('/city', lat: lat, lon: lon, nearby: true, radius: radius, unit: unit, country: country, state: state, limit: limit, deep: deep, lang: lang, type: type, grain: grain, hierarchy: hierarchy, min_population: min_population, max_population: max_population, timezone: timezone, bbox: bbox, sort: sort, order: order, cursor: cursor, romanized: romanized, format: 'list', countries: city_csv(countries), exclude_countries: city_csv(exclude_countries), timezones: city_csv(timezones), min_elevation: min_elevation, max_elevation: max_elevation)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def city_siblings(id, limit: nil, cursor: nil, hierarchy: false, deep: false, lang: nil, romanized: false)
|
|
168
|
+
get("/city/id/#{seg(id)}/siblings", limit: limit, cursor: cursor, romanized: romanized, hierarchy: hierarchy, deep: deep, lang: lang)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
|
|
131
172
|
def postal(code, country: nil, deep: false, lang: nil)
|
|
132
173
|
get("/postal/#{seg(code)}", country: country, deep: deep, lang: lang)
|
|
133
174
|
end
|
|
@@ -281,14 +322,6 @@ module ParseAPI
|
|
|
281
322
|
get('/useragent', { deep: deep }, { 'User-Agent' => ua })
|
|
282
323
|
end
|
|
283
324
|
|
|
284
|
-
def vehicle(vin, deep: false)
|
|
285
|
-
get("/vehicle/#{seg(vin)}", deep: deep)
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
def vin(vin, deep: false)
|
|
289
|
-
get("/vin/#{seg(vin)}", deep: deep)
|
|
290
|
-
end
|
|
291
|
-
|
|
292
325
|
# US NAICS 2022 definition and hierarchy.
|
|
293
326
|
# Compatibility names for Industry.
|
|
294
327
|
def naics(code, deep: false)
|
|
@@ -576,6 +609,11 @@ module ParseAPI
|
|
|
576
609
|
metered ? 0 : DEFAULT_RETRIES
|
|
577
610
|
end
|
|
578
611
|
|
|
612
|
+
def city_csv(value)
|
|
613
|
+
value.is_a?(Array) ? value.join(',') : value
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
|
|
579
617
|
def build_error(status, body, retry_after = nil)
|
|
580
618
|
parsed = begin
|
|
581
619
|
JSON.parse(body)
|
|
@@ -583,7 +621,7 @@ module ParseAPI
|
|
|
583
621
|
{}
|
|
584
622
|
end
|
|
585
623
|
parsed = {} unless parsed.is_a?(Hash)
|
|
586
|
-
Error.new(
|
|
624
|
+
error = Error.new(
|
|
587
625
|
status: status,
|
|
588
626
|
code: parsed['code'].is_a?(String) ? parsed['code'] : 'unknown_error',
|
|
589
627
|
message: parsed['message'].is_a?(String) ? parsed['message'] : "Request failed with status #{status}",
|
|
@@ -591,6 +629,19 @@ module ParseAPI
|
|
|
591
629
|
request_id: parsed['request_id'].is_a?(String) ? parsed['request_id'] : nil,
|
|
592
630
|
retry_after: retry_after
|
|
593
631
|
)
|
|
632
|
+
if status == 409 && error.code == 'ambiguous_city' && parsed['candidates'].is_a?(Array)
|
|
633
|
+
candidates = parsed['candidates'].first(2).map do |row|
|
|
634
|
+
next unless row.is_a?(Hash) && row['id'].is_a?(String) && /\Acity_[a-z0-9]{12}\z/.match?(row['id']) && row['object'] == 'city'
|
|
635
|
+
candidate = { 'id' => row['id'], 'object' => 'city' }
|
|
636
|
+
%w[name name_local country country_name state state_name type].each do |field|
|
|
637
|
+
value = row[field]
|
|
638
|
+
candidate[field] = value if row.key?(field) && (value.nil? || (value.is_a?(String) && value.length <= 255))
|
|
639
|
+
end
|
|
640
|
+
candidate
|
|
641
|
+
end.compact
|
|
642
|
+
error.instance_variable_set(:@candidates, candidates)
|
|
643
|
+
end
|
|
644
|
+
error
|
|
594
645
|
end
|
|
595
646
|
end
|
|
596
647
|
end
|
data/lib/parseapi/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: parseapi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.10.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ParseAPI
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description:
|
|
14
14
|
email:
|