parseapi 0.3.2 → 1.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69e639b49f6986257ea0f5cf3b5424867fd563efd4d6762e06657c0349e2071b
4
- data.tar.gz: 7212244b17194211f3a5a400a932df526dc4ff6ce04d7fc28ed94ede12486ebd
3
+ metadata.gz: 8229ca82d3288ebdae0032fc5d3d8865d12b241f1627b6ccf2409e568eb5501a
4
+ data.tar.gz: 70929f039ede8fa845145a3c3803c186d1a8dfb8dd2af4b45b6fcf058772cb1f
5
5
  SHA512:
6
- metadata.gz: 255d9d9ae3fddb1bd3e35ba6fd5d9fb06a74c8d8a603bd24d29bc558f5d0b2587fdb5a60df2cf2bae3be703234febfa72c61c22e508d72b1e5ebc045eef74ab0
7
- data.tar.gz: 6438c6a8761ecb4b5cbb77af884ebfb20b2e755d51f52ce1832d553e845322804b6c4184498eb49203c1d78ecdca608cc263a5a9606bc69cf91c9ea388a2c205
6
+ metadata.gz: 0b22da2a9cec679abc8ed1a8a60dcd2365cdb2776c49c58089df907653fd6971198d317348f72d4a5b8cf8d0c7ae8c8f51db34516aa3817cfe99df4fe830b983
7
+ data.tar.gz: 79894060499900eb0a2210fd36b260b68bba1b837a537274efe81e4aa0cc1353a4f29e89b19429486242b71993b3eb014c6109bd64a5caf2b4b6a1f21fbda87f
data/README.md CHANGED
@@ -11,6 +11,39 @@ country = parse.country('US')
11
11
 
12
12
  Get a key at [parseapi.com](https://parseapi.com). The client also reads `PARSEAPI_KEY` from the environment.
13
13
 
14
+ ## API versions
15
+
16
+ Version 1.0.0 explicitly selects the API contract supported by this SDK. It sends `Parse-Version: 2.0.0` on every lookup so responses match the API contract supported by the package. Your key and the team's saved default stay the same.
17
+
18
+ Upgrade the dependency in staging, review the [release notes](https://parseapi.com/docs/releases), and test the application before deploying the same code and dependency version to production. Commit your dependency lockfile so the tested package travels with your deployment. Future major SDK upgrades can select a newer API contract.
19
+
20
+ Previously published SDKs keep their existing behavior and use the team's default. Requests without `Parse-Version` also use that default, managed in [Dashboard API version](https://parseapi.com/dashboard/versions). Keep it unchanged while older applications depend on it. Rolling back to an SDK without a version header restores the team default, so rollback only restores the old contract when that default has stayed unchanged.
21
+
22
+ The package owns its supported API version. For direct HTTP integrations, an explicit `Parse-Version` header selects a supported contract. See [API versions and migration](https://parseapi.com/docs/versioning).
23
+
24
+ ## Weather from a postal code
25
+
26
+ Start with the postal code, then pass its coordinates to weather. Reuse the client from the example above.
27
+
28
+ ```ruby
29
+ place = parse.postal('28202', country: 'US')
30
+ lat, lon = place.values_at('latitude', 'longitude')
31
+ unless lat.nil? || lon.nil?
32
+ weather = parse.weather(lat, lon)
33
+ puts weather
34
+ end
35
+ ```
36
+
37
+ The coordinates represent the postal area. Weather is for that point. Missing coordinates skip the weather lookup. This composition performs two ordinary lookups when coordinates are available, with the retry policy below.
38
+
39
+ ## Supply the context you know
40
+
41
+ Pass `country` when a postal code or national phone number needs disambiguation. A complete international phone number already carries its country context. For a numeric date such as `03/04/2026`, supply the intended `format`. Defaults resolve what the input establishes. Ambiguous input needs your context.
42
+
43
+ Results are plain data. Pass a returned code or coordinate to another operation when the task needs it. Check nullable values before composing the next call.
44
+
45
+ Use `parse.postal('28202', country: 'US', deep: true)` for US ZIP tax references. `deep.tax` names the levy and `deep.tax_rate` is a percentage, so `7.9` means 7.9%. The state, county, city and special components explain that combined rate. An exact address can differ. Country and state lookups provide their own geographic reference rates, which should not be added to the ZIP rate. `nil` means unknown and `0` means known zero. Country `deep.tax_id_format` and `deep.tax_id_regex` describe registration-number format only. Use `vat` for a metered registration check with `deep` explicitly enabled.
46
+
14
47
  ## Calls
15
48
 
16
49
  One method per endpoint, named after the route.
@@ -21,6 +54,7 @@ parse.ip_self
21
54
  parse.email('hello@gmail.com')
22
55
  parse.vat('DE136695976')
23
56
  parse.iban('DE89370400440532013000')
57
+ parse.bin('424242')
24
58
  parse.npi('1881018208')
25
59
  parse.phone('+14155552671')
26
60
  parse.carrier('+14155552671')
@@ -52,9 +86,12 @@ parse.currency('USD')
52
86
  parse.currency_rate('USD', 'EUR')
53
87
  parse.language('en')
54
88
  parse.name('BILLY OSHALL')
55
- parse.timezone('America/New_York')
56
- parse.timezone('America/New_York', at: '2026-09-05T15:00', to: 'Europe/London')
57
- parse.timezone_at(35.2271, -80.8431)
89
+ parse.name('Andrea', country: 'IT', deep: true)
90
+ parse.name('Robert James Smith', deep: true, name_locale: 'en')
91
+ parse.time # UTC now
92
+ parse.time('America/New_York')
93
+ parse.time('America/New_York', at: '2026-09-05T15:00', to: 'Europe/London')
94
+ parse.time_at(35.2271, -80.8431)
58
95
  parse.date('03/04/2026', format: 'mdy')
59
96
  parse.date_today(to: '2026-12-25')
60
97
  parse.holiday('US', year: 2026)
@@ -67,23 +104,110 @@ parse.domain('example.com')
67
104
  parse.asn('AS13335')
68
105
  parse.mac('00:1B:63:84:45:E6')
69
106
  parse.mx('example.com')
107
+ parse.dns('example.com')
108
+ parse.dns('_dmarc.example.com', type: 'TXT')
70
109
  parse.useragent(ua_string)
71
110
  parse.vin('1HGCM82633A004352')
111
+ parse.naics('541511')
112
+ parse.naics_search('coffee shop', limit: 5)
72
113
  parse.tariff('8471.30.01.00', origin: 'CN', deep: true)
73
114
  parse.tariff_search('sunglasses')
74
115
  parse.emoji('rocket')
75
116
  parse.emoji_search('fire')
76
117
  ```
77
118
 
119
+ NAICS paid deep records include classification `deep.exclusions`, each with a description and linked codes. Generic exclusions can have no linked codes. Omitted or null exclusions in older responses remain unknown. Search results also include `match`: the matched `field` (`name`, `term` or `naics`) and `text`, plus `corrections` with `from` and `to` tokens for typo fallback. Corrections are empty for exact, plural and prefix matches. Direct code lookups omit `match`. Older responses may omit it.
120
+
78
121
  Each lookup returns a plain hash with string keys. Related lookups are separate calls, such as `country_states('US')`. Reading the result makes no further requests. New response fields and `nil` values are preserved.
79
122
 
123
+ DNS uses pooled requests on every plan. Omit `type` to check A, AAAA, CNAME, MX, NS, TXT, SOA, CAA, SRV and PTR. Records contain `name`, `type`, `ttl` in seconds and a DNS presentation `value`. TXT values retain quoting and chunk boundaries. A selected question can include its CNAME chain. Empty records mean no records. Lookup failures remain errors.
124
+
125
+ Name paid deep includes flat `short`, `directory`, and `initials` fields beside `gender` and `salutation`. `name_locale` selects CLDR formatting rules and defaults to `en`. It changes formatting only. Country remains gender context, and unavailable formatting is null. Older responses may omit these fields.
126
+
127
+ ## Display language
128
+
129
+ Choose display names for one request:
130
+
131
+ ```ruby
132
+ parse.country('DE', lang: 'fr')
133
+ ```
134
+
135
+ `lang` is optional on geography lookups and their lists/searches, Currency lookup, Language, Date, Time/Timezone, Emoji lookup/search, and unit discovery. IP, ASN, Company and NPI also accept it for their geographic labels. Codes, native names, quantities and response structure retain their meanings. Source coverage determines which labels are translated; unavailable labels use the API's documented fallback.
136
+
137
+ The next call keeps its usual default unless it also supplies `lang`. Existing `deep` rules still apply. Date `format` and measurement `locale` remain explicit input-parsing controls.
138
+
139
+ ## Time
140
+
141
+ `time` returns local ISO `at` with its UTC offset and integer Unix seconds in `unix`. The core `offset` preserves exact precision. Optional `deep.offset_seconds` gives the numeric offset, while `deep.offset_minutes` gives whole minutes. Historical offsets and ISO times can include offset seconds. Omitted `at` means now. With `to`, an offsetless `at` is source wall time. Otherwise it is UTC. Include an offset for repeated local times around a clock change. Current time and conversion use pooled requests on every plan. Coordinate clock fields can be null when the timezone is unknown. Existing `timezone` methods remain supported.
142
+
143
+ ## Measurements
144
+
145
+ ```ruby
146
+ result = parse.measure('5 ft 11 in', to: 'cm')
147
+ units = parse.measure_units(unit: 'm')
148
+ ```
149
+
150
+ `amount` is a decimal string, such as `"180.34"`. Without `to`, the API returns the canonical unit for the measurement type. Pass `locale` for number formatting and `system` (`us` or `imperial`) when a customary unit needs context. Ambiguous input returns `valid: false`, a `reason`, and available `choices`. Invalid or incompatible target units use the normal API error.
151
+
152
+ Unit discovery accepts optional `query`, `type`, and `unit` filters. `unit` selects compatible targets. Omit the filters for the reviewed catalog. Both operations use pooled requests.
153
+
154
+ ## Place statistics and optional detail
155
+
156
+ Postal and District paid profiles include `deep.property_tax` where supported. It contains `annual_median`, `currency` and `period`: median annual property tax payable on owner-occupied homes in the statistical area. The amount is adjusted to the final year of the reporting period (`YYYY-YYYY`). This is an area statistic, not a rate or an individual property bill. Unsupported, missing and censored estimates are null.
157
+
158
+ ```ruby
159
+ place = parse.postal('28202', country: 'US', deep: true)
160
+ property_tax = place.dig('deep', 'property_tax')
161
+ ```
162
+
163
+ Read `population_period` alongside `population`: a reporting year (`YYYY`) or period (`YYYY-YYYY`), null when unknown or unverifiable. Keep missing or null values unknown and preserve a known zero. These fields belong to full place profiles. State district lists include each district's population and period. Postal nearby and distance detail remains metropolitan associations only. Continent population stays in core.
164
+
165
+ 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.
166
+
167
+ Point returns the timezone ID with the core location. Its optional deep detail adds terrain and compact nearest-city context on every plan. A nearest city is null when none is within 200 km.
168
+
169
+ Weather returns current conditions by default. Paid deep adds specialist current measurements, forecasts and related detail. A past `date` is a UTC day and requires deep: it adds `deep.history` alongside current conditions. Date alone does not request history.
170
+
171
+ ```ruby
172
+ parse.weather(40.7128, -74.006, deep: true, date: '2026-08-15')
173
+ ```
174
+
175
+ Tariff starts with the general schedule line. Paid deep adds units and the special and other schedule columns. An optional origin then resolves country-specific measures. The three calls below show those successive choices. Without origin, schedule detail is still returned and origin-dependent fields are null. A null effective rate is not a zero rate.
176
+
177
+ ```ruby
178
+ parse.tariff('8471.30.01.00')
179
+ parse.tariff('8471.30.01.00', deep: true)
180
+ parse.tariff('8471.30.01.00', deep: true, origin: 'CN')
181
+ ```
182
+
183
+ Address search uses context from the form: prefer postal, or city and state. An optional end-user `ip` is a locality hint for server-side calls. An empty result explains itself with `reason`: `more_input`, `missing_context` or `no_matches`. With suggestions, reason is null. Older responses may omit it, and future reasons remain strings. Catalog and lookup failures use the existing API errors.
184
+
185
+ HLR reports status at the last check. `live` means assigned and `connected` means reachable at that check. Cached results may be returned. Null means unconfirmed. Deep diagnostics stay within the same metered lookup.
186
+
80
187
  ## Deep
81
188
 
82
- Pass `deep: true` to include the nested `deep` object with richer fields.
189
+ Choose enrichment for the question you need answered.
190
+
191
+ | Operation | What `deep` requests |
192
+ |---|---|
193
+ | IP | Richer IP fields included with a paid plan. No separate check meter. |
194
+ | Domain | Registration dates, registrar, status and DNSSEC, included with a paid plan. Use `dns` for DNS records and `mx` for mail routing. |
195
+ | Email | A metered deliverability check, using included email checks or enabled on-demand usage. |
196
+ | VAT | A metered registry check where supported, using included VAT checks or enabled on-demand usage. |
197
+ | Phone, Time, Date, Currency, Language, Emoji, IBAN, Point | Optional detail in the same pooled request on every plan. |
198
+ | Country, State, District, City, Postal | The place profile on paid plans, including demographic and tax facts where held. |
199
+ | Name, NAICS | Name evidence or the industry definition profile on paid plans. |
200
+ | VIN, NPI, Tariff, Company | The complete product detail bag on paid plans. |
201
+ | Weather | Specialist current measurements and the existing forecast, alert, air and history bag on paid plans. |
202
+ | Carrier, HLR | Optional diagnostic detail within the same metered core unit, including Free allowance units. No second gate or additional check. |
203
+
204
+ Carrier, caller, and HLR are separate metered operations. Choose them explicitly when you need their answers. Ordinary lookups retry twice by default. Metered checks use one attempt by default. Setting retries explicitly can repeat paid usage.
205
+
206
+ Without `deep`, the response omits that key. When requested, it is an empty object if access is locked or the operation has no deep fields. Otherwise it contains the available fields. A missing or null field means unknown.
83
207
 
84
208
  ```ruby
85
209
  ip = parse.ip('52.94.76.10', deep: true)
86
- ip['deep']['datacenter'] # true
210
+ ip.dig('deep', 'datacenter') # true, false, or nil
87
211
  ```
88
212
 
89
213
  ## Errors
@@ -124,3 +248,16 @@ Requires Ruby 3.0 or later. Standard library only, zero dependencies.
124
248
  ## Docs
125
249
 
126
250
  Full field reference for every endpoint: [parseapi.com/docs](https://parseapi.com/docs)
251
+
252
+ BIN lookup accepts 6-11 digits as a string, including leading zeros. Spaces and hyphens are accepted. `prefix` is the actual longest match and can be shorter than the input. Unknown reference fields are null. `deep` adds an empty object on every plan.
253
+
254
+
255
+ ## Optional detail
256
+
257
+ The default response answers the common task. Ask for `deep` when you need more detail about that same result. Core fields stay equal. City, NAICS and Emoji searches put detail inside each result. Postal nearby and distance put metropolitan detail beside the entity it describes. Time conversion keeps target detail in `to.deep`; only the source has `deep.next_dst`.
258
+
259
+ ```ruby
260
+ basic = parse.time('America/New_York')
261
+ detail = parse.time('America/New_York', deep: true)
262
+ puts basic['at'], detail.dig('deep', 'next_dst')
263
+ ```
@@ -18,6 +18,8 @@ module ParseAPI
18
18
  end
19
19
 
20
20
  class Client
21
+ API_VERSION = '2.0.0'.freeze
22
+ private_constant :API_VERSION
21
23
  DEFAULT_BASE_URL = 'https://api.parseapi.com'.freeze
22
24
  DEFAULT_TIMEOUT = 10
23
25
  DEFAULT_RETRIES = 2
@@ -30,6 +32,7 @@ module ParseAPI
30
32
  ].freeze
31
33
 
32
34
  def initialize(api_key = nil, base_url: nil, timeout: nil, retries: nil, transport: nil)
35
+ # You found Dev. https://parseapi.com/dev
33
36
  @api_key = api_key || ENV['PARSEAPI_KEY']
34
37
  raise ArgumentError, 'parseapi: missing API key. Pass one or set PARSEAPI_KEY.' if @api_key.nil? || @api_key.empty?
35
38
 
@@ -54,140 +57,173 @@ module ParseAPI
54
57
  "#<#{self.class} api_key=[REDACTED] timeout=#{@timeout} retries=#{@retries.nil? ? 'auto' : @retries}>"
55
58
  end
56
59
 
57
- # --- Lookup methods (one per endpoint, named after the route) ---
58
60
 
59
- def ip(ip, deep: false)
60
- get("/ip/#{seg(ip)}", deep: deep)
61
+ # Look up an IP. Deep enrichment is included with a paid plan, without a separate check meter.
62
+ def ip(ip, deep: false, lang: nil)
63
+ get("/ip/#{seg(ip)}", deep: deep, lang: lang)
61
64
  end
62
65
 
63
- def ip_self(deep: false)
64
- get('/ip', deep: deep)
66
+ # Look up the public IP making this request. On a server, this is the server's IP.
67
+ def ip_self(deep: false, lang: nil)
68
+ get('/ip', deep: deep, lang: lang)
65
69
  end
66
70
 
67
- def continent(code)
68
- get("/continent/#{seg(code)}")
71
+ def continent(code, lang: nil)
72
+ get("/continent/#{seg(code)}", lang: lang)
69
73
  end
70
74
 
71
- def continent_countries(code)
72
- get("/continent/#{seg(code)}/countries")
75
+ def continent_countries(code, lang: nil)
76
+ get("/continent/#{seg(code)}/countries", lang: lang)
73
77
  end
74
78
 
75
79
  def bloc(code)
76
80
  get("/bloc/#{seg(code)}")
77
81
  end
78
82
 
79
- def bloc_countries(code)
80
- get("/bloc/#{seg(code)}/countries")
83
+ def bloc_countries(code, lang: nil)
84
+ get("/bloc/#{seg(code)}/countries", lang: lang)
81
85
  end
82
86
 
83
- def country(code)
84
- get("/country/#{seg(code)}")
87
+ def country(code, deep: false, lang: nil)
88
+ get("/country/#{seg(code)}", deep: deep, lang: lang)
85
89
  end
86
90
 
87
- def country_states(code)
88
- get("/country/#{seg(code)}/states")
91
+ def country_states(code, lang: nil)
92
+ get("/country/#{seg(code)}/states", lang: lang)
89
93
  end
90
94
 
91
- def state(code, country: nil)
92
- get("/state/#{seg(code)}", country: country)
95
+ def state(code, country: nil, deep: false, lang: nil)
96
+ get("/state/#{seg(code)}", country: country, deep: deep, lang: lang)
93
97
  end
94
98
 
95
- def state_districts(code, country: nil)
96
- get("/state/#{seg(code)}/districts", country: country)
99
+ def state_districts(code, country: nil, deep: false, lang: nil)
100
+ get("/state/#{seg(code)}/districts", country: country, deep: deep, lang: lang)
97
101
  end
98
102
 
99
- def district(code, country: nil, state: nil)
100
- get("/district/#{seg(code)}", country: country, state: state)
103
+ def district(code, country: nil, state: nil, deep: false, lang: nil)
104
+ get("/district/#{seg(code)}", country: country, state: state, deep: deep, lang: lang)
101
105
  end
102
106
 
103
- def city(name, country: nil, state: nil)
104
- get("/city/#{seg(name)}", country: country, state: state)
107
+ def city(name, country: nil, state: nil, deep: false, lang: nil)
108
+ get("/city/#{seg(name)}", country: country, state: state, deep: deep, lang: lang)
105
109
  end
106
110
 
107
- def city_id(id)
108
- get("/city/id/#{seg(id)}")
111
+ def city_id(id, deep: false, lang: nil)
112
+ get("/city/id/#{seg(id)}", deep: deep, lang: lang)
109
113
  end
110
114
 
111
- def city_search(query, country: nil, state: nil, limit: nil)
112
- get('/city', q: query, country: country, state: state, limit: limit)
115
+ def city_search(query, country: nil, state: nil, limit: nil, deep: false, lang: nil)
116
+ get('/city', q: query, country: country, state: state, limit: limit, deep: deep, lang: lang)
113
117
  end
114
118
 
115
- def city_nearest(lat, lon)
116
- get('/city', lat: lat, lon: lon)
119
+ def city_nearest(lat, lon, deep: false, lang: nil)
120
+ get('/city', lat: lat, lon: lon, deep: deep, lang: lang)
117
121
  end
118
122
 
119
- def city_nearby(name, radius: nil, unit: nil, country: nil, state: nil, limit: nil)
120
- get("/city/#{seg(name)}/nearby", radius: radius, unit: unit, country: country, state: state, limit: limit)
123
+ def city_nearby(name, radius: nil, unit: nil, country: nil, state: nil, limit: nil, deep: false, lang: nil)
124
+ get("/city/#{seg(name)}/nearby", radius: radius, unit: unit, country: country, state: state, limit: limit, deep: deep, lang: lang)
121
125
  end
122
126
 
123
- def postal(code, country: nil)
124
- get("/postal/#{seg(code)}", country: country)
127
+ # Look up a postal area. Pass country when known. Check nullable coordinates before another
128
+ # location lookup.
129
+ def postal(code, country: nil, deep: false, lang: nil)
130
+ get("/postal/#{seg(code)}", country: country, deep: deep, lang: lang)
125
131
  end
126
132
 
127
- def postal_nearby(code, country: nil, radius: nil, unit: nil)
128
- get("/postal/#{seg(code)}/nearby", country: country, radius: radius, unit: unit)
133
+ def postal_nearby(code, country: nil, radius: nil, unit: nil, deep: false, lang: nil)
134
+ get("/postal/#{seg(code)}/nearby", country: country, radius: radius, unit: unit, deep: deep, lang: lang)
129
135
  end
130
136
 
131
- def postal_distance(from, to, country: nil)
132
- get("/postal/#{seg(from)}/distance/#{seg(to)}", country: country)
137
+ def postal_distance(from, to, country: nil, deep: false, lang: nil)
138
+ get("/postal/#{seg(from)}/distance/#{seg(to)}", country: country, deep: deep, lang: lang)
133
139
  end
134
140
 
135
141
  def address(address, country: nil, deep: false)
136
142
  get("/address/#{seg(address)}", country: country, deep: deep)
137
143
  end
138
144
 
145
+ # Find address suggestions using the context supplied. Prefer postal, or city and state, from
146
+ # the form; ip is an optional end-user locality hint for server-side calls. An empty result has
147
+ # reason more_input, missing_context or no_matches. Suggestions have reason null. Operational
148
+ # failures are errors.
139
149
  def address_search(query, country: nil, postal: nil, city: nil, state: nil, ip: nil)
140
150
  get('/address', q: query, country: country, postal: postal, city: city, state: state, ip: ip)
141
151
  end
142
152
 
143
- def company(number, country: nil, deep: false)
144
- get("/company/#{seg(number)}", country: country, deep: deep)
153
+ def company(number, country: nil, deep: false, lang: nil)
154
+ get("/company/#{seg(number)}", country: country, deep: deep, lang: lang)
145
155
  end
146
156
 
157
+ # Parse an email and check its format and domain. Deep explicitly requests a metered
158
+ # deliverability check. Deep checks use one attempt by default. An explicit retry count can
159
+ # repeat paid usage.
147
160
  def email(email, deep: false)
148
161
  get("/email/#{seg(email)}", deep: deep)
149
162
  end
150
163
 
164
+ # Check VAT format and checksum. Deep requests a metered registry check where supported. Deep
165
+ # checks use one attempt by default. Supply your own VAT number for a consultation reference
166
+ # when supported.
151
167
  def vat(number, country: nil, deep: false, from: nil)
152
168
  get("/vat/#{seg(number)}", country: country, deep: deep, from: from)
153
169
  end
154
170
 
155
- def iban(iban, country: nil)
156
- get("/iban/#{seg(iban)}", country: country)
171
+ def iban(iban, country: nil, deep: false)
172
+ get("/iban/#{seg(iban)}", country: country, deep: deep)
157
173
  end
158
174
 
159
- def npi(npi, deep: false)
160
- get("/npi/#{seg(npi)}", deep: deep)
175
+ # Look up a 6-11 digit card prefix, preserving leading zeros.
176
+ def bin(bin, deep: false)
177
+ get("/bin/#{seg(bin)}", deep: deep)
161
178
  end
162
179
 
180
+
181
+ def npi(npi, deep: false, lang: nil)
182
+ get("/npi/#{seg(npi)}", deep: deep, lang: lang)
183
+ end
184
+
185
+ # Parse a phone number and its formats. Pass country for national numbers when needed. Deep
186
+ # adds numbering-plan geography on every plan. Carrier, caller, and HLR are separate metered lookups.
163
187
  def phone(number, country: nil, deep: false)
164
188
  get("/phone/#{seg(number)}", country: country, deep: deep)
165
189
  end
166
190
 
167
- def carrier(number, country: nil)
168
- get("/carrier/#{seg(number)}", country: country)
191
+ # Request a metered carrier lookup. No automatic retries by default.
192
+ def carrier(number, country: nil, deep: false)
193
+ get("/carrier/#{seg(number)}", country: country, deep: deep)
169
194
  end
170
195
 
196
+ # Request a metered caller-name lookup for a NANP number. No automatic retries by default.
171
197
  def caller(number, country: nil)
172
198
  get("/caller/#{seg(number)}", country: country)
173
199
  end
174
200
 
175
- def hlr(number, country: nil)
176
- get("/hlr/#{seg(number)}", country: country)
201
+ # Look up phone status at the last check. Live means assigned and connected means reachable at
202
+ # that check. Cached results may be returned. Null means unconfirmed. Deep adds network
203
+ # diagnostics within the same metered lookup. No automatic retries by default.
204
+ def hlr(number, country: nil, deep: false)
205
+ get("/hlr/#{seg(number)}", country: country, deep: deep)
177
206
  end
178
207
 
208
+ # Check whether a domain is registered. Deep adds registration dates, registrar, status and DNSSEC on paid plans.
179
209
  def domain(domain, deep: false)
180
210
  get("/domain/#{seg(domain)}", deep: deep)
181
211
  end
182
212
 
183
- def asn(asn)
184
- get("/asn/#{seg(asn)}")
213
+ def asn(asn, lang: nil)
214
+ get("/asn/#{seg(asn)}", lang: lang)
185
215
  end
186
216
 
187
217
  def mac(mac)
188
218
  get("/mac/#{seg(mac)}")
189
219
  end
190
220
 
221
+ # Published DNS records with TTLs. Omit type to check all supported types.
222
+ # Type selects the question, including its CNAME chain. Pooled on every plan.
223
+ def dns(domain, type: nil)
224
+ get("/dns/#{seg(domain)}", type: type)
225
+ end
226
+
191
227
  def mx(domain)
192
228
  get("/mx/#{seg(domain)}")
193
229
  end
@@ -200,6 +236,20 @@ module ParseAPI
200
236
  get("/vin/#{seg(vin)}", deep: deep)
201
237
  end
202
238
 
239
+ # US NAICS 2022 definition and hierarchy.
240
+ def naics(code, deep: false)
241
+ get("/naics/#{seg(code)}", deep: deep)
242
+ end
243
+
244
+ # Keyword search. Limit defaults to 10 and accepts 1-50.
245
+ def naics_search(query, limit: nil, deep: false)
246
+ get('/naics', q: query, limit: limit, deep: deep)
247
+ end
248
+
249
+ # Look up the general US duty schedule line. Paid deep adds units and the special and other
250
+ # schedule columns. Add origin with deep to resolve country-specific measures. Without origin,
251
+ # schedule detail remains available and origin-dependent fields are null. A null effective rate
252
+ # is not a zero rate.
203
253
  def tariff(code, deep: false, origin: nil)
204
254
  get("/tariff/#{seg(code)}", deep: deep, origin: origin)
205
255
  end
@@ -208,36 +258,46 @@ module ParseAPI
208
258
  get('/tariff', q: query)
209
259
  end
210
260
 
211
- def currency(code)
212
- get("/currency/#{seg(code)}")
261
+ def currency(code, deep: false, lang: nil)
262
+ get("/currency/#{seg(code)}", deep: deep, lang: lang)
213
263
  end
214
264
 
215
265
  def currency_rate(base, quote, date: nil, amount: nil)
216
266
  get("/currency/#{seg(base)}/#{seg(quote)}", date: date, amount: amount)
217
267
  end
218
268
 
219
- def language(code)
220
- get("/language/#{seg(code)}")
269
+ def language(code, deep: false, lang: nil)
270
+ get("/language/#{seg(code)}", deep: deep, lang: lang)
221
271
  end
222
272
 
223
- def name(name)
224
- get("/name/#{seg(name)}")
273
+ # Name locale selects CLDR formatting, default en, without changing parsing or gender context.
274
+ def name(name, country: nil, deep: false, name_locale: nil)
275
+ get("/name/#{seg(name)}", country: country, deep: deep, name_locale: name_locale)
225
276
  end
226
277
 
227
- def timezone(id, at: nil, to: nil)
228
- get("/timezone/#{seg(id)}", at: at, to: to)
278
+ # Current local time, UTC by default. With to, offsetless at is source wall time.
279
+ def time(timezone = nil, at: nil, to: nil, deep: false, lang: nil)
280
+ get(timezone.nil? ? '/time' : "/time/#{seg(timezone)}", at: at, to: to, deep: deep, lang: lang)
229
281
  end
230
282
 
231
- def timezone_at(lat, lon, at: nil)
232
- get('/timezone', lat: lat, lon: lon, at: at)
283
+ def time_at(lat, lon, at: nil, to: nil, deep: false, lang: nil)
284
+ get('/time', lat: lat, lon: lon, at: at, to: to, deep: deep, lang: lang)
233
285
  end
234
286
 
235
- def date(date, format: nil, to: nil)
236
- get("/date/#{seg(date)}", format: format, to: to)
287
+ def timezone(id, at: nil, to: nil, deep: false, lang: nil)
288
+ get("/timezone/#{seg(id)}", at: at, to: to, deep: deep, lang: lang)
237
289
  end
238
290
 
239
- def date_today(to: nil)
240
- get('/date', to: to)
291
+ def timezone_at(lat, lon, at: nil, deep: false, lang: nil)
292
+ get('/timezone', lat: lat, lon: lon, at: at, deep: deep, lang: lang)
293
+ end
294
+
295
+ def date(date, format: nil, to: nil, deep: false, lang: nil)
296
+ get("/date/#{seg(date)}", format: format, to: to, deep: deep, lang: lang)
297
+ end
298
+
299
+ def date_today(to: nil, deep: false, lang: nil)
300
+ get('/date', to: to, deep: deep, lang: lang)
241
301
  end
242
302
 
243
303
  def holiday(country, year: nil)
@@ -252,20 +312,37 @@ module ParseAPI
252
312
  get('/elevation', lat: lat, lon: lon)
253
313
  end
254
314
 
255
- def point(lat, lon, deep: false)
256
- get('/point', lat: lat, lon: lon, deep: deep)
315
+ # Resolve the country, state, district and timezone at coordinates. Deep adds terrain and
316
+ # compact nearest-city context on every plan. The timezone ID stays in core. The nearest city is
317
+ # null when none is within 200 km.
318
+ def point(lat, lon, deep: false, lang: nil)
319
+ get('/point', lat: lat, lon: lon, deep: deep, lang: lang)
257
320
  end
258
321
 
322
+ # Get current conditions in metric and imperial units. Paid deep adds specialist current
323
+ # measurements, forecasts and related detail. With deep, date selects a past UTC day (YYYY-MM-
324
+ # DD) in deep.history alongside current conditions. Date alone does not request history.
259
325
  def weather(lat, lon, deep: false, date: nil)
260
326
  get('/weather', lat: lat, lon: lon, deep: deep, date: date)
261
327
  end
262
328
 
263
- def emoji(emoji)
264
- get("/emoji/#{seg(emoji)}")
329
+ def emoji(emoji, deep: false, lang: nil)
330
+ get("/emoji/#{seg(emoji)}", deep: deep, lang: lang)
331
+ end
332
+
333
+ def emoji_search(query, limit: nil, deep: false, lang: nil)
334
+ get('/emoji', q: query, limit: limit, deep: deep, lang: lang)
335
+ end
336
+
337
+ # Parse or convert a measurement. Amount is a decimal string. Without to, use the
338
+ # type's canonical unit. Locale and system (us or imperial) resolve explicit ambiguity.
339
+ def measure(measure, to: nil, locale: nil, system: nil)
340
+ get("/measure/#{seg(measure)}", to: to, locale: locale, system: system)
265
341
  end
266
342
 
267
- def emoji_search(query, limit: nil)
268
- get('/emoji', q: query, limit: limit)
343
+ # Discover reviewed units. unit filters compatible conversion targets.
344
+ def measure_units(query: nil, type: nil, unit: nil, lang: nil)
345
+ get('/measure/units', q: query, type: type, unit: unit, lang: lang)
269
346
  end
270
347
 
271
348
  private
@@ -306,7 +383,7 @@ module ParseAPI
306
383
  end
307
384
 
308
385
  def request_headers(extra)
309
- { 'X-API-Key' => @api_key, 'User-Agent' => "parseapi-ruby/#{VERSION}" }.merge(extra)
386
+ { 'X-API-Key' => @api_key, 'User-Agent' => "parseapi-ruby/#{VERSION}" }.merge(extra).merge('Parse-Version' => API_VERSION)
310
387
  end
311
388
 
312
389
  # Returns [status, headers_hash, body_string]. Overridden in tests.
@@ -1,3 +1,3 @@
1
1
  module ParseAPI
2
- VERSION = '0.3.2'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
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: 0.3.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ParseAPI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-07 00:00:00.000000000 Z
11
+ date: 2026-09-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: