@roxyapi/sdk 1.2.32 → 1.2.34

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.
package/AGENTS.md CHANGED
@@ -46,7 +46,7 @@ Type `roxy.` to see all available namespaces. Type `roxy.{domain}.` to see every
46
46
  | `roxy.numerology` | 16 | Production-ready Pythagorean numerology API + hosted MCP for AI agents and developers |
47
47
  | `roxy.tarot` | 10 | Production-ready tarot card reading API + hosted MCP for AI agents and developers |
48
48
  | `roxy.humanDesign` | 12 | Generate the full Human Design bodygraph from a birth moment: type, strategy, inner authority, profile, definition, i... |
49
- | `roxy.forecast` | 5 | Merge upcoming transit aspects, sign ingresses, retrograde stations, Vimshottari dasha changes, and biorhythm critica... |
49
+ | `roxy.forecast` | 5 | Merge upcoming transit aspects, sign ingresses, retrograde stations, new and full moons, biorhythm critical days, and... |
50
50
  | `roxy.biorhythm` | 6 | The most complete biorhythm API + remote MCP for AI agents and developers |
51
51
  | `roxy.iching` | 9 | I-Ching oracle API + hosted MCP for AI agents and developers |
52
52
  | `roxy.crystals` | 12 | Production-ready crystal healing API + hosted MCP for AI agents and developers |
@@ -57,7 +57,7 @@ Type `roxy.` to see all available namespaces. Type `roxy.{domain}.` to see every
57
57
  | `roxy.languages` | 1 | List the response languages accepted by the `lang` query parameter on every i18n-aware endpoint |
58
58
  <!-- END:DOMAINS -->
59
59
 
60
- **Total:** 130 endpoints across 10 product domains plus usage and languages. Counts auto-sync from `specs/openapi.json` at release time.
60
+ **Total:** 148 endpoints across 12 product domains plus usage and languages. Counts auto-sync from `specs/openapi.json` at release time.
61
61
 
62
62
  ## Quality guidelines for agents
63
63
 
@@ -177,6 +177,8 @@ Ordered by domain priority (Western, Vedic, Numerology, Tarot, Biorhythm, I Chin
177
177
  | Three-card spread | `roxy.tarot.castThreeCard({ body: { question } })` |
178
178
  | Celtic Cross | `roxy.tarot.castCelticCross({ body: { question } })` |
179
179
  | Yes / no tarot | `roxy.tarot.castYesNo({ body: { question } })` |
180
+ | Human Design bodygraph | `roxy.humanDesign.generateBodygraph({ body: { date, time, latitude, longitude, timezone } })` |
181
+ | Forecast timeline | `roxy.forecast.generateTimeline({ body: { birthData, startDate, endDate } })` |
180
182
  | Daily biorhythm | `roxy.biorhythm.getDailyBiorhythm({ body: { seed } })` |
181
183
  | Biorhythm forecast | `roxy.biorhythm.getForecast({ body: { birthDate } })` |
182
184
  | Biorhythm compatibility | `roxy.biorhythm.calculateBioCompatibility({ body: { person1, person2 } })` |
package/README.md CHANGED
@@ -90,7 +90,7 @@ const { latitude, longitude, timezone } = data.cities[0];
90
90
  | `roxy.numerology` | 16 | Production-ready Pythagorean numerology API + hosted MCP for AI agents and developers |
91
91
  | `roxy.tarot` | 10 | Production-ready tarot card reading API + hosted MCP for AI agents and developers |
92
92
  | `roxy.humanDesign` | 12 | Generate the full Human Design bodygraph from a birth moment: type, strategy, inner authority, profile, definition, i... |
93
- | `roxy.forecast` | 5 | Merge upcoming transit aspects, sign ingresses, retrograde stations, Vimshottari dasha changes, and biorhythm critica... |
93
+ | `roxy.forecast` | 5 | Merge upcoming transit aspects, sign ingresses, retrograde stations, new and full moons, biorhythm critical days, and... |
94
94
  | `roxy.biorhythm` | 6 | The most complete biorhythm API + remote MCP for AI agents and developers |
95
95
  | `roxy.iching` | 9 | I-Ching oracle API + hosted MCP for AI agents and developers |
96
96
  | `roxy.crystals` | 12 | Production-ready crystal healing API + hosted MCP for AI agents and developers |
@@ -217,7 +217,49 @@ const { data: answer } = await roxy.tarot.castYesNo({ body: { question: 'Should
217
217
  // answer.answer ("Yes" | "No" | "Maybe"), answer.strength
218
218
  ```
219
219
 
220
- ### 5. Biorhythm API (daily check-in, forecast, compatibility)
220
+ ### 5. Human Design API (bodygraph in one call)
221
+
222
+ The breakout 2026 self-discovery category. One call returns the full bodygraph from a birth moment: energy type, strategy, authority, profile, definition, incarnation cross, the 9 centers, defined channels, and all 26 gate activations. The Design side is solved on the exact 88-degree solar arc, not approximated as calendar days. No coordinates needed beyond the birth instant, so there is no location setup step.
223
+
224
+ ```typescript
225
+ // Full bodygraph. Type, strategy, profile, and definition are always populated.
226
+ const { data: hd } = await roxy.humanDesign.generateBodygraph({
227
+ body: {
228
+ date: '1990-07-04',
229
+ time: '10:12:00',
230
+ latitude: 28.6139,
231
+ longitude: 77.209,
232
+ timezone: 5.5,
233
+ },
234
+ });
235
+ // hd.type, hd.strategy, hd.profile, hd.definition
236
+ // hd.centers, hd.channels, hd.gates, hd.incarnationCross
237
+ ```
238
+
239
+ ### 6. Forecast API (cross-domain timeline)
240
+
241
+ The first cross-domain, stateless forecast in the catalog. One call merges Western transit-to-natal aspects, sign ingresses, retrograde stations, Vedic Vimshottari dasha boundaries, and biorhythm critical days into a single significance-scored, time-ordered timeline. The window is clamped to a 90-day horizon. Forecast feeds, transit alerts, and timing tools are the buyers.
242
+
243
+ ```typescript
244
+ // Merged timeline. Each event carries date, domain, type, description, and significance.
245
+ const { data: timeline } = await roxy.forecast.generateTimeline({
246
+ body: {
247
+ birthData: {
248
+ date: '1990-07-04',
249
+ time: '10:12:00',
250
+ latitude: 28.6139,
251
+ longitude: 77.209,
252
+ timezone: 5.5,
253
+ },
254
+ startDate: '2026-06-01',
255
+ endDate: '2026-06-30',
256
+ },
257
+ });
258
+ // timeline.count, timeline.events
259
+ // timeline.events[0].date, timeline.events[0].domain, timeline.events[0].description, timeline.events[0].significance
260
+ ```
261
+
262
+ ### 7. Biorhythm API (daily check-in, forecast, compatibility)
221
263
 
222
264
  Zero competition domain. Steady search volume with the top Google result being a static calculator page. Pure land-grab for wellness, productivity, sports, and couples apps.
223
265
 
@@ -233,7 +275,7 @@ const { data: forecast } = await roxy.biorhythm.getForecast({
233
275
  });
234
276
  ```
235
277
 
236
- ### 6. I Ching API (daily hexagram, coin cast, 64-hexagram catalog)
278
+ ### 8. I Ching API (daily hexagram, coin cast, 64-hexagram catalog)
237
279
 
238
280
  Meditation apps, decision-making tools, and wisdom chatbots. `i ching API` and `hexagram API` are the keywords.
239
281
 
@@ -247,7 +289,7 @@ const { data: hexagrams } = await roxy.iching.listHexagrams({});
247
289
  // hexagrams.hexagrams has 64 entries
248
290
  ```
249
291
 
250
- ### 7. Crystals API (by zodiac, by chakra, birthstone)
292
+ ### 9. Crystals API (by zodiac, by chakra, birthstone)
251
293
 
252
294
  Crystal retail and metaphysical shops use these to build "crystals for [sign]" and "[chakra] chakra stones" pages.
253
295
 
@@ -263,7 +305,7 @@ const { data: byChakra } = await roxy.crystals.getCrystalsByChakra({ path: { cha
263
305
  const { data: birthstone } = await roxy.crystals.getBirthstones({ path: { month: 4 } });
264
306
  ```
265
307
 
266
- ### 8. Dream interpretation API (symbol dictionary, search)
308
+ ### 10. Dream interpretation API (symbol dictionary, search)
267
309
 
268
310
  Thousands of dream symbols. `dream meaning` is among the highest-volume spiritual searches on Google. Journal apps, AI therapy chatbots, and self-discovery products are the buyers.
269
311
 
@@ -277,7 +319,7 @@ const { data: results } = await roxy.dreams.searchDreamSymbols({ query: { q: 'fl
277
319
  // results.symbols is an array of matching symbols
278
320
  ```
279
321
 
280
- ### 9. Angel Numbers API (1111, 222, 333 meanings plus universal lookup)
322
+ ### 11. Angel Numbers API (1111, 222, 333 meanings plus universal lookup)
281
323
 
282
324
  Gen Z spiritual-tok fuel. `111 meaning`, `222 meaning`, `333 angel number` are evergreen viral queries with massive shareability.
283
325
 
@@ -90,10 +90,10 @@ var stripEmptySlots = (params) => {
90
90
  };
91
91
  var buildClientParams = (args, fields) => {
92
92
  const params = {
93
- body: {},
94
- headers: {},
95
- path: {},
96
- query: {}
93
+ body: /* @__PURE__ */ Object.create(null),
94
+ headers: /* @__PURE__ */ Object.create(null),
95
+ path: /* @__PURE__ */ Object.create(null),
96
+ query: /* @__PURE__ */ Object.create(null)
97
97
  };
98
98
  const map = buildKeyMap(fields);
99
99
  let config;
@@ -222,7 +222,7 @@ var serializeQueryKeyValue = (value) => {
222
222
  };
223
223
 
224
224
  // src/core/serverSentEvents.gen.ts
225
- var createSseClient = ({
225
+ function createSseClient({
226
226
  onRequest,
227
227
  onSseError,
228
228
  onSseEvent,
@@ -234,7 +234,7 @@ var createSseClient = ({
234
234
  sseSleepFn,
235
235
  url,
236
236
  ...options
237
- }) => {
237
+ }) {
238
238
  let lastEventId;
239
239
  const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
240
240
  const createStream = async function* () {
@@ -278,7 +278,7 @@ var createSseClient = ({
278
278
  const { done, value } = await reader.read();
279
279
  if (done) break;
280
280
  buffer += value;
281
- buffer = buffer.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
281
+ buffer = buffer.replace(/\r\n?/g, "\n");
282
282
  const chunks = buffer.split("\n\n");
283
283
  buffer = chunks.pop() ?? "";
284
284
  for (const chunk of chunks) {
@@ -346,7 +346,7 @@ var createSseClient = ({
346
346
  };
347
347
  const stream = createStream();
348
348
  return { stream };
349
- };
349
+ }
350
350
 
351
351
  // src/core/pathSerializer.gen.ts
352
352
  var separatorArrayExplode = (style) => {
@@ -663,11 +663,8 @@ var checkForExistence = (options, name) => {
663
663
  }
664
664
  return false;
665
665
  };
666
- var setAuthParams = async ({
667
- security,
668
- ...options
669
- }) => {
670
- for (const auth of security) {
666
+ async function setAuthParams(options) {
667
+ for (const auth of options.security ?? []) {
671
668
  if (checkForExistence(options, auth.name)) {
672
669
  continue;
673
670
  }
@@ -692,7 +689,7 @@ var setAuthParams = async ({
692
689
  break;
693
690
  }
694
691
  }
695
- };
692
+ }
696
693
  var buildUrl = (options) => getUrl({
697
694
  baseUrl: options.baseUrl,
698
695
  path: options.path,
@@ -818,10 +815,7 @@ var createClient = (config = {}) => {
818
815
  serializedBody: void 0
819
816
  };
820
817
  if (opts.security) {
821
- await setAuthParams({
822
- ...opts,
823
- security: opts.security
824
- });
818
+ await setAuthParams(opts);
825
819
  }
826
820
  if (opts.requestValidator) {
827
821
  await opts.requestValidator(opts);
@@ -832,131 +826,121 @@ var createClient = (config = {}) => {
832
826
  if (opts.body === void 0 || opts.serializedBody === "") {
833
827
  opts.headers.delete("Content-Type");
834
828
  }
835
- const url = buildUrl(opts);
836
- return { opts, url };
829
+ const resolvedOpts = opts;
830
+ const url = buildUrl(resolvedOpts);
831
+ return { opts: resolvedOpts, url };
837
832
  };
838
833
  const request = async (options) => {
839
- const { opts, url } = await beforeRequest(options);
840
- const requestInit = {
841
- redirect: "follow",
842
- ...opts,
843
- body: getValidRequestBody(opts)
844
- };
845
- let request2 = new Request(url, requestInit);
846
- for (const fn of interceptors.request.fns) {
847
- if (fn) {
848
- request2 = await fn(request2, opts);
849
- }
850
- }
851
- const _fetch = opts.fetch;
834
+ const throwOnError = options.throwOnError ?? _config.throwOnError;
835
+ const responseStyle = options.responseStyle ?? _config.responseStyle;
836
+ let request2;
852
837
  let response;
853
838
  try {
854
- response = await _fetch(request2);
855
- } catch (error2) {
856
- let finalError2 = error2;
857
- for (const fn of interceptors.error.fns) {
839
+ const { opts, url } = await beforeRequest(options);
840
+ const requestInit = {
841
+ redirect: "follow",
842
+ ...opts,
843
+ body: getValidRequestBody(opts)
844
+ };
845
+ request2 = new Request(url, requestInit);
846
+ for (const fn of interceptors.request.fns) {
858
847
  if (fn) {
859
- finalError2 = await fn(error2, void 0, request2, opts);
848
+ request2 = await fn(request2, opts);
860
849
  }
861
850
  }
862
- finalError2 = finalError2 || {};
863
- if (opts.throwOnError) {
864
- throw finalError2;
851
+ const _fetch = opts.fetch;
852
+ response = await _fetch(request2);
853
+ for (const fn of interceptors.response.fns) {
854
+ if (fn) {
855
+ response = await fn(response, request2, opts);
856
+ }
865
857
  }
866
- return opts.responseStyle === "data" ? void 0 : {
867
- error: finalError2,
858
+ const result = {
868
859
  request: request2,
869
- response: void 0
860
+ response
870
861
  };
871
- }
872
- for (const fn of interceptors.response.fns) {
873
- if (fn) {
874
- response = await fn(response, request2, opts);
875
- }
876
- }
877
- const result = {
878
- request: request2,
879
- response
880
- };
881
- if (response.ok) {
882
- const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
883
- if (response.status === 204 || response.headers.get("Content-Length") === "0") {
884
- let emptyData;
862
+ if (response.ok) {
863
+ const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
864
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
865
+ let emptyData;
866
+ switch (parseAs) {
867
+ case "arrayBuffer":
868
+ case "blob":
869
+ case "text":
870
+ emptyData = await response[parseAs]();
871
+ break;
872
+ case "formData":
873
+ emptyData = new FormData();
874
+ break;
875
+ case "stream":
876
+ emptyData = response.body;
877
+ break;
878
+ case "json":
879
+ default:
880
+ emptyData = {};
881
+ break;
882
+ }
883
+ return opts.responseStyle === "data" ? emptyData : {
884
+ data: emptyData,
885
+ ...result
886
+ };
887
+ }
888
+ let data;
885
889
  switch (parseAs) {
886
890
  case "arrayBuffer":
887
891
  case "blob":
892
+ case "formData":
888
893
  case "text":
889
- emptyData = await response[parseAs]();
894
+ data = await response[parseAs]();
890
895
  break;
891
- case "formData":
892
- emptyData = new FormData();
896
+ case "json": {
897
+ const text = await response.text();
898
+ data = text ? JSON.parse(text) : {};
893
899
  break;
900
+ }
894
901
  case "stream":
895
- emptyData = response.body;
896
- break;
897
- case "json":
898
- default:
899
- emptyData = {};
900
- break;
902
+ return opts.responseStyle === "data" ? response.body : {
903
+ data: response.body,
904
+ ...result
905
+ };
901
906
  }
902
- return opts.responseStyle === "data" ? emptyData : {
903
- data: emptyData,
907
+ if (parseAs === "json") {
908
+ if (opts.responseValidator) {
909
+ await opts.responseValidator(data);
910
+ }
911
+ if (opts.responseTransformer) {
912
+ data = await opts.responseTransformer(data);
913
+ }
914
+ }
915
+ return opts.responseStyle === "data" ? data : {
916
+ data,
904
917
  ...result
905
918
  };
906
919
  }
907
- let data;
908
- switch (parseAs) {
909
- case "arrayBuffer":
910
- case "blob":
911
- case "formData":
912
- case "text":
913
- data = await response[parseAs]();
914
- break;
915
- case "json": {
916
- const text = await response.text();
917
- data = text ? JSON.parse(text) : {};
918
- break;
919
- }
920
- case "stream":
921
- return opts.responseStyle === "data" ? response.body : {
922
- data: response.body,
923
- ...result
924
- };
920
+ const textError = await response.text();
921
+ let jsonError;
922
+ try {
923
+ jsonError = JSON.parse(textError);
924
+ } catch {
925
925
  }
926
- if (parseAs === "json") {
927
- if (opts.responseValidator) {
928
- await opts.responseValidator(data);
929
- }
930
- if (opts.responseTransformer) {
931
- data = await opts.responseTransformer(data);
926
+ throw jsonError ?? textError;
927
+ } catch (error) {
928
+ let finalError = error;
929
+ for (const fn of interceptors.error.fns) {
930
+ if (fn) {
931
+ finalError = await fn(finalError, response, request2, options);
932
932
  }
933
933
  }
934
- return opts.responseStyle === "data" ? data : {
935
- data,
936
- ...result
937
- };
938
- }
939
- const textError = await response.text();
940
- let jsonError;
941
- try {
942
- jsonError = JSON.parse(textError);
943
- } catch {
944
- }
945
- const error = jsonError ?? textError;
946
- let finalError = error;
947
- for (const fn of interceptors.error.fns) {
948
- if (fn) {
949
- finalError = await fn(error, response, request2, opts);
934
+ finalError = finalError || {};
935
+ if (throwOnError) {
936
+ throw finalError;
950
937
  }
938
+ return responseStyle === "data" ? void 0 : {
939
+ error: finalError,
940
+ request: request2,
941
+ response
942
+ };
951
943
  }
952
- finalError = finalError || {};
953
- if (opts.throwOnError) {
954
- throw finalError;
955
- }
956
- return opts.responseStyle === "data" ? void 0 : {
957
- error: finalError,
958
- ...result
959
- };
960
944
  };
961
945
  const makeMethodFn = (method) => (options) => request({ ...options, method });
962
946
  const makeSseFn = (method) => async (options) => {
@@ -964,7 +948,6 @@ var createClient = (config = {}) => {
964
948
  return createSseClient({
965
949
  ...opts,
966
950
  body: opts.body,
967
- headers: opts.headers,
968
951
  method,
969
952
  onRequest: async (url2, init) => {
970
953
  let request2 = new Request(url2, init);
@@ -1 +1 @@
1
- {"version":3,"file":"client.gen.d.ts","sourceRoot":"","sources":["../../src/client/client.gen.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAA0C,MAAM,aAAa,CAAC;AAgB1F,eAAO,MAAM,YAAY,GAAI,SAAQ,MAAW,KAAG,MA4QlD,CAAC"}
1
+ {"version":3,"file":"client.gen.d.ts","sourceRoot":"","sources":["../../src/client/client.gen.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAA0C,MAAM,aAAa,CAAC;AAgB1F,eAAO,MAAM,YAAY,GAAI,SAAQ,MAAW,KAAG,MA+PlD,CAAC"}