diff --git a/.sdk.json b/.sdk.json
index a288390..4c020c5 100644
--- a/.sdk.json
+++ b/.sdk.json
@@ -1,5 +1,5 @@
{
- "id": "88c7735c-a5b9-4bd6-aac7-a4e1dbdd3200",
+ "id": "a3774c17-32bb-4640-bcac-f894d270aca5",
"tracked_paths": [
{
"editable": true,
@@ -49,6 +49,22 @@
"editable": true,
"path": "src/resources/v1/README.md"
},
+ {
+ "editable": true,
+ "path": "src/resources/v1/account/README.md"
+ },
+ {
+ "editable": true,
+ "path": "src/resources/v1/account/index.ts"
+ },
+ {
+ "editable": false,
+ "path": "src/resources/v1/account/request-types.ts"
+ },
+ {
+ "editable": true,
+ "path": "src/resources/v1/account/resource-client.ts"
+ },
{
"editable": true,
"path": "src/resources/v1/ai-clothes-changer/README.md"
@@ -593,6 +609,34 @@
"editable": true,
"path": "src/types/index.ts"
},
+ {
+ "editable": false,
+ "path": "src/types/v1-account-list-response-subscription-billing-interval-enum.ts"
+ },
+ {
+ "editable": false,
+ "path": "src/types/v1-account-list-response-subscription-discount.ts"
+ },
+ {
+ "editable": false,
+ "path": "src/types/v1-account-list-response-subscription-price.ts"
+ },
+ {
+ "editable": false,
+ "path": "src/types/v1-account-list-response-subscription-status-enum.ts"
+ },
+ {
+ "editable": false,
+ "path": "src/types/v1-account-list-response-subscription.ts"
+ },
+ {
+ "editable": false,
+ "path": "src/types/v1-account-list-response-tier-enum.ts"
+ },
+ {
+ "editable": false,
+ "path": "src/types/v1-account-list-response.ts"
+ },
{
"editable": false,
"path": "src/types/v1-ai-clothes-changer-create-body-assets-garment-type-enum.ts"
@@ -1285,6 +1329,10 @@
"editable": false,
"path": "src/types/v1-video-to-video-create-response.ts"
},
+ {
+ "editable": false,
+ "path": "test/v1-account.test.ts"
+ },
{
"editable": false,
"path": "test/v1-ai-clothes-changer.test.ts"
diff --git a/README.md b/README.md
index ac828e4..2e05c57 100644
--- a/README.md
+++ b/README.md
@@ -201,6 +201,10 @@ Valid values are: `none`, `error`, `warn`, `info`, `debug` (case insensitive). I
## Module Documentation and Snippets
+### [v1.account](src/resources/v1/account/README.md)
+
+- [list](src/resources/v1/account/README.md#list) - Get account details
+
### [v1.aiClothesChanger](src/resources/v1/ai-clothes-changer/README.md)
- [create](src/resources/v1/ai-clothes-changer/README.md#create) - AI Clothes Changer
diff --git a/package-lock.json b/package-lock.json
index 2c42678..a6848a6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "magic-hour",
- "version": "0.74.1",
+ "version": "0.75.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "magic-hour",
- "version": "0.74.1",
+ "version": "0.75.0",
"license": "MIT",
"dependencies": {
"make-api-request-js": "^0.2.1",
diff --git a/package.json b/package.json
index 7525a28..4326601 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "magic-hour",
- "version": "0.74.1",
+ "version": "0.75.0",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
diff --git a/src/README.md b/src/README.md
index 9da01a7..918c235 100644
--- a/src/README.md
+++ b/src/README.md
@@ -2,6 +2,7 @@
## Submodules
+- [account](resources/v1/account/README.md) - account
- [ai-clothes-changer](resources/v1/ai-clothes-changer/README.md) - ai-clothes-changer
- [ai-face-editor](resources/v1/ai-face-editor/README.md) - ai-face-editor
- [ai-gif-generator](resources/v1/ai-gif-generator/README.md) - ai-gif-generator
diff --git a/src/environment.ts b/src/environment.ts
index 87e73f7..479a40f 100644
--- a/src/environment.ts
+++ b/src/environment.ts
@@ -1,4 +1,4 @@
export enum Environment {
Environment = "https://api.magichour.ai",
- MockServer = "https://api.sideko.dev/v1/mock/magichour/magic-hour/0.78.1",
+ MockServer = "https://api.sideko.dev/v1/mock/magichour/magic-hour/0.79.0",
}
diff --git a/src/resources/v1/README.md b/src/resources/v1/README.md
index adf38aa..2488fd8 100644
--- a/src/resources/v1/README.md
+++ b/src/resources/v1/README.md
@@ -2,6 +2,7 @@
## Submodules
+- [account](account/README.md) - account
- [ai-clothes-changer](ai-clothes-changer/README.md) - ai-clothes-changer
- [ai-face-editor](ai-face-editor/README.md) - ai-face-editor
- [ai-gif-generator](ai-gif-generator/README.md) - ai-gif-generator
diff --git a/src/resources/v1/account/README.md b/src/resources/v1/account/README.md
new file mode 100644
index 0000000..b33a0e5
--- /dev/null
+++ b/src/resources/v1/account/README.md
@@ -0,0 +1,30 @@
+# v1.account
+
+## Module Functions
+
+### Get account details
+
+Get the current credit balance and subscription details of the account that owns the API key.
+
+**API Endpoint**: `GET /v1/account`
+
+#### Example Snippet
+
+```typescript
+import { Client } from "magic-hour";
+
+const client = new Client({ token: process.env["API_TOKEN"]!! });
+const res = await client.v1.account.list();
+```
+
+#### Response
+
+##### Type
+
+[V1AccountListResponse](/src/types/v1-account-list-response.ts)
+
+##### Example
+
+```typescript
+{"credits": 12500, "email": "user@example.com", "id": "cuid-example", "subscription": {"billingInterval": "month", "cancelAtPeriodEnd": false, "currentPeriodEnd": "2026-10-01T00:00:00.000Z", "discount": {"amountOff": 123, "percentOff": 20.0}, "name": "Pro", "price": {"amount": 4900, "currency": "usd"}, "status": "active"}, "tier": "pro"}
+```
diff --git a/src/resources/v1/account/index.ts b/src/resources/v1/account/index.ts
new file mode 100644
index 0000000..de1a56d
--- /dev/null
+++ b/src/resources/v1/account/index.ts
@@ -0,0 +1 @@
+export { AccountClient } from "./resource-client";
diff --git a/src/resources/v1/account/resource-client.ts b/src/resources/v1/account/resource-client.ts
new file mode 100644
index 0000000..e886683
--- /dev/null
+++ b/src/resources/v1/account/resource-client.ts
@@ -0,0 +1,33 @@
+import {
+ ApiPromise,
+ CoreClient,
+ CoreResourceClient,
+ RequestOptions,
+ ResourceClientOptions,
+} from "make-api-request-js";
+
+import * as types from "magic-hour/types";
+import { Schemas$V1AccountListResponse } from "magic-hour/types/v1-account-list-response";
+
+export class AccountClient extends CoreResourceClient {
+ constructor(coreClient: CoreClient, opts: ResourceClientOptions) {
+ super(coreClient, opts);
+ }
+
+ /**
+ * Get account details
+ *
+ * Get the current credit balance and subscription details of the account that owns the API key.
+ *
+ * GET /v1/account
+ */
+ list(opts?: RequestOptions): ApiPromise {
+ return this._client.makeRequest({
+ method: "get",
+ path: "/v1/account",
+ auth: ["bearerAuth"],
+ responseSchema: Schemas$V1AccountListResponse.in,
+ opts,
+ });
+ }
+}
diff --git a/src/resources/v1/index.ts b/src/resources/v1/index.ts
index ac5d7f3..0c5afec 100644
--- a/src/resources/v1/index.ts
+++ b/src/resources/v1/index.ts
@@ -1,3 +1,4 @@
+export * as account from "./account";
export * as aiClothesChanger from "./ai-clothes-changer";
export * as aiFaceEditor from "./ai-face-editor";
export * as aiGifGenerator from "./ai-gif-generator";
diff --git a/src/resources/v1/resource-client.ts b/src/resources/v1/resource-client.ts
index f829e3a..dd3238f 100644
--- a/src/resources/v1/resource-client.ts
+++ b/src/resources/v1/resource-client.ts
@@ -4,6 +4,7 @@ import {
ResourceClientOptions,
} from "make-api-request-js";
+import { AccountClient } from "magic-hour/resources/v1/account";
import { AiClothesChangerClient } from "magic-hour/resources/v1/ai-clothes-changer";
import { AiFaceEditorClient } from "magic-hour/resources/v1/ai-face-editor";
import { AiGifGeneratorClient } from "magic-hour/resources/v1/ai-gif-generator";
@@ -38,6 +39,7 @@ import { VideoProjectsClient } from "magic-hour/resources/v1/video-projects";
import { VideoToVideoClient } from "magic-hour/resources/v1/video-to-video";
export class V1Client extends CoreResourceClient {
+ private _accountLazy?: AccountClient; // lazy-loading cache
private _characterReplaceLazy?: CharacterReplaceClient; // lazy-loading cache
private _aiVideoEditorLazy?: AiVideoEditorClient; // lazy-loading cache
private _audioToVideoLazy?: AudioToVideoClient; // lazy-loading cache
@@ -75,6 +77,7 @@ export class V1Client extends CoreResourceClient {
constructor(coreClient: CoreClient, opts: ResourceClientOptions) {
super(coreClient, opts);
if (this._opts.lazyLoad === false) {
+ this.account;
this.aiClothesChanger;
this.aiFaceEditor;
this.aiGifGenerator;
@@ -455,4 +458,14 @@ export class V1Client extends CoreResourceClient {
))
);
}
+
+ get account(): AccountClient {
+ return (
+ this._accountLazy ??
+ (this._accountLazy = new (require("./account").AccountClient)(
+ this._client,
+ this._opts,
+ ))
+ );
+ }
}
diff --git a/src/types/index.ts b/src/types/index.ts
index af86115..f0a22df 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,3 +1,10 @@
+export { V1AccountListResponse } from "./v1-account-list-response";
+export { V1AccountListResponseSubscription } from "./v1-account-list-response-subscription";
+export { V1AccountListResponseSubscriptionBillingIntervalEnum } from "./v1-account-list-response-subscription-billing-interval-enum";
+export { V1AccountListResponseSubscriptionDiscount } from "./v1-account-list-response-subscription-discount";
+export { V1AccountListResponseSubscriptionPrice } from "./v1-account-list-response-subscription-price";
+export { V1AccountListResponseSubscriptionStatusEnum } from "./v1-account-list-response-subscription-status-enum";
+export { V1AccountListResponseTierEnum } from "./v1-account-list-response-tier-enum";
export { V1AiClothesChangerCreateBody } from "./v1-ai-clothes-changer-create-body";
export { V1AiClothesChangerCreateBodyAssets } from "./v1-ai-clothes-changer-create-body-assets";
export { V1AiClothesChangerCreateBodyAssetsGarmentTypeEnum } from "./v1-ai-clothes-changer-create-body-assets-garment-type-enum";
diff --git a/src/types/v1-account-list-response-subscription-billing-interval-enum.ts b/src/types/v1-account-list-response-subscription-billing-interval-enum.ts
new file mode 100644
index 0000000..7be625e
--- /dev/null
+++ b/src/types/v1-account-list-response-subscription-billing-interval-enum.ts
@@ -0,0 +1,6 @@
+/**
+ * How often the subscription is billed. `null` if unknown.
+ */
+export type V1AccountListResponseSubscriptionBillingIntervalEnum =
+ | "month"
+ | "year";
diff --git a/src/types/v1-account-list-response-subscription-discount.ts b/src/types/v1-account-list-response-subscription-discount.ts
new file mode 100644
index 0000000..9a94495
--- /dev/null
+++ b/src/types/v1-account-list-response-subscription-discount.ts
@@ -0,0 +1,70 @@
+import { zodTransform } from "make-api-request-js";
+import * as z from "zod";
+
+/**
+ * Discount applied to the subscription. `null` if no discount is applied.
+ */
+export type V1AccountListResponseSubscriptionDiscount = {
+ /**
+ * Fixed amount taken off `price.amount` each billing interval, in the smallest unit of the currency. `null` if the discount is a percentage.
+ */
+ amountOff: number | null;
+ /**
+ * Percentage taken off `price.amount` each billing interval. `null` if the discount is a fixed amount.
+ */
+ percentOff: number | null;
+};
+
+/**
+ * @internal
+ * V1AccountListResponseSubscriptionDiscount without any key transformation, this is what
+ * we expect to come in as network data
+ */
+export type External$V1AccountListResponseSubscriptionDiscount = {
+ amount_off: number | null;
+ percent_off: number | null;
+};
+
+/**
+ * Takes network data, validates it, and transforms keys to match typescript object V1AccountListResponseSubscriptionDiscount
+ */
+const SchemaIn$V1AccountListResponseSubscriptionDiscount: z.ZodType<
+ V1AccountListResponseSubscriptionDiscount, // output type of this zod object
+ z.ZodTypeDef,
+ unknown
+> = z
+ .object({
+ amount_off: z.number().int().nullable(),
+ percent_off: z.number().nullable(),
+ })
+ .transform((obj) => {
+ return zodTransform(obj, {
+ amount_off: "amountOff",
+ percent_off: "percentOff",
+ });
+ });
+
+/**
+ * @internal
+ * Takes typescript data, validates it, and maps keys to match the expected external object External$V1AccountListResponseSubscriptionDiscount
+ */
+const SchemaOut$V1AccountListResponseSubscriptionDiscount: z.ZodType<
+ External$V1AccountListResponseSubscriptionDiscount, // output type of this zod object
+ z.ZodTypeDef,
+ V1AccountListResponseSubscriptionDiscount // the object to be transformed
+> = z
+ .object({
+ amountOff: z.number().int().nullable(),
+ percentOff: z.number().nullable(),
+ })
+ .transform((obj) => {
+ return zodTransform(obj, {
+ amountOff: "amount_off",
+ percentOff: "percent_off",
+ });
+ });
+
+export const Schemas$V1AccountListResponseSubscriptionDiscount = {
+ in: SchemaIn$V1AccountListResponseSubscriptionDiscount,
+ out: SchemaOut$V1AccountListResponseSubscriptionDiscount,
+};
diff --git a/src/types/v1-account-list-response-subscription-price.ts b/src/types/v1-account-list-response-subscription-price.ts
new file mode 100644
index 0000000..bac6ee1
--- /dev/null
+++ b/src/types/v1-account-list-response-subscription-price.ts
@@ -0,0 +1,70 @@
+import { zodTransform } from "make-api-request-js";
+import * as z from "zod";
+
+/**
+ * V1AccountListResponseSubscriptionPrice
+ */
+export type V1AccountListResponseSubscriptionPrice = {
+ /**
+ * Price charged per billing interval, in the smallest unit of the currency (e.g. 4900 is $49.00 for `usd`). Discounts are not applied.
+ */
+ amount: number;
+ /**
+ * Three-letter ISO 4217 currency code, lowercase.
+ */
+ currency: string;
+};
+
+/**
+ * @internal
+ * V1AccountListResponseSubscriptionPrice without any key transformation, this is what
+ * we expect to come in as network data
+ */
+export type External$V1AccountListResponseSubscriptionPrice = {
+ amount: number;
+ currency: string;
+};
+
+/**
+ * Takes network data, validates it, and transforms keys to match typescript object V1AccountListResponseSubscriptionPrice
+ */
+const SchemaIn$V1AccountListResponseSubscriptionPrice: z.ZodType<
+ V1AccountListResponseSubscriptionPrice, // output type of this zod object
+ z.ZodTypeDef,
+ unknown
+> = z
+ .object({
+ amount: z.number().int(),
+ currency: z.string(),
+ })
+ .transform((obj) => {
+ return zodTransform(obj, {
+ amount: "amount",
+ currency: "currency",
+ });
+ });
+
+/**
+ * @internal
+ * Takes typescript data, validates it, and maps keys to match the expected external object External$V1AccountListResponseSubscriptionPrice
+ */
+const SchemaOut$V1AccountListResponseSubscriptionPrice: z.ZodType<
+ External$V1AccountListResponseSubscriptionPrice, // output type of this zod object
+ z.ZodTypeDef,
+ V1AccountListResponseSubscriptionPrice // the object to be transformed
+> = z
+ .object({
+ amount: z.number().int(),
+ currency: z.string(),
+ })
+ .transform((obj) => {
+ return zodTransform(obj, {
+ amount: "amount",
+ currency: "currency",
+ });
+ });
+
+export const Schemas$V1AccountListResponseSubscriptionPrice = {
+ in: SchemaIn$V1AccountListResponseSubscriptionPrice,
+ out: SchemaOut$V1AccountListResponseSubscriptionPrice,
+};
diff --git a/src/types/v1-account-list-response-subscription-status-enum.ts b/src/types/v1-account-list-response-subscription-status-enum.ts
new file mode 100644
index 0000000..b5dfdd3
--- /dev/null
+++ b/src/types/v1-account-list-response-subscription-status-enum.ts
@@ -0,0 +1,6 @@
+/**
+ * Status of the subscription.
+ * - `active`: payments are up to date.
+ * - `past_due`: the latest payment failed. `tier` is `free` until payment succeeds. The subscription is canceled if payment keeps failing.
+ */
+export type V1AccountListResponseSubscriptionStatusEnum = "active" | "past_due";
diff --git a/src/types/v1-account-list-response-subscription.ts b/src/types/v1-account-list-response-subscription.ts
new file mode 100644
index 0000000..5116a6d
--- /dev/null
+++ b/src/types/v1-account-list-response-subscription.ts
@@ -0,0 +1,127 @@
+import { zodTransform } from "make-api-request-js";
+import * as z from "zod";
+
+import {
+ External$V1AccountListResponseSubscriptionDiscount,
+ Schemas$V1AccountListResponseSubscriptionDiscount,
+ V1AccountListResponseSubscriptionDiscount,
+} from "./v1-account-list-response-subscription-discount";
+import {
+ External$V1AccountListResponseSubscriptionPrice,
+ Schemas$V1AccountListResponseSubscriptionPrice,
+ V1AccountListResponseSubscriptionPrice,
+} from "./v1-account-list-response-subscription-price";
+
+/**
+ * Details of the account's subscription plan. `null` if the account has no subscription, e.g. a free account, an account that only purchased credit packs, or an account on usage-based API pricing.
+ *
+ * Reflects the plan currently configured on the subscription. If a plan change is scheduled, `tier` stays on the current plan until the next payment succeeds, so `tier` and `name` can briefly disagree.
+ */
+export type V1AccountListResponseSubscription = {
+ /**
+ * How often the subscription is billed. `null` if unknown.
+ */
+ billingInterval: ("month" | "year") | null;
+ /**
+ * Whether the subscription is scheduled to end at `current_period_end` instead of renewing. The subscription stays usable until then.
+ */
+ cancelAtPeriodEnd: boolean;
+ /**
+ * End of the current billing period, in ISO 8601 format. The subscription renews at this time, or ends if `cancel_at_period_end` is `true`.
+ */
+ currentPeriodEnd: string | null;
+ /**
+ * Discount applied to the subscription. `null` if no discount is applied.
+ */
+ discount: V1AccountListResponseSubscriptionDiscount | null;
+ /**
+ * Name of the current subscription plan, e.g. `Creator`, `Pro`, `Pro Plus`, `Business`. `null` if the plan cannot be determined. Use `tier` for a machine-readable value.
+ */
+ name: string | null;
+ price: V1AccountListResponseSubscriptionPrice;
+ /**
+ * Status of the subscription.
+ * - `active`: payments are up to date.
+ * - `past_due`: the latest payment failed. `tier` is `free` until payment succeeds. The subscription is canceled if payment keeps failing.
+ */
+ status: "active" | "past_due";
+};
+
+/**
+ * @internal
+ * V1AccountListResponseSubscription without any key transformation, this is what
+ * we expect to come in as network data
+ */
+export type External$V1AccountListResponseSubscription = {
+ billing_interval: ("month" | "year") | null;
+ cancel_at_period_end: boolean;
+ current_period_end: string | null;
+ discount: External$V1AccountListResponseSubscriptionDiscount | null;
+ name: string | null;
+ price: External$V1AccountListResponseSubscriptionPrice;
+ status: "active" | "past_due";
+};
+
+/**
+ * Takes network data, validates it, and transforms keys to match typescript object V1AccountListResponseSubscription
+ */
+const SchemaIn$V1AccountListResponseSubscription: z.ZodType<
+ V1AccountListResponseSubscription, // output type of this zod object
+ z.ZodTypeDef,
+ unknown
+> = z
+ .object({
+ billing_interval: z.enum(["month", "year"]).nullable(),
+ cancel_at_period_end: z.boolean(),
+ current_period_end: z.string().nullable(),
+ discount: Schemas$V1AccountListResponseSubscriptionDiscount.in.nullable(),
+ name: z.string().nullable(),
+ price: Schemas$V1AccountListResponseSubscriptionPrice.in,
+ status: z.enum(["active", "past_due"]),
+ })
+ .transform((obj) => {
+ return zodTransform(obj, {
+ billing_interval: "billingInterval",
+ cancel_at_period_end: "cancelAtPeriodEnd",
+ current_period_end: "currentPeriodEnd",
+ discount: "discount",
+ name: "name",
+ price: "price",
+ status: "status",
+ });
+ });
+
+/**
+ * @internal
+ * Takes typescript data, validates it, and maps keys to match the expected external object External$V1AccountListResponseSubscription
+ */
+const SchemaOut$V1AccountListResponseSubscription: z.ZodType<
+ External$V1AccountListResponseSubscription, // output type of this zod object
+ z.ZodTypeDef,
+ V1AccountListResponseSubscription // the object to be transformed
+> = z
+ .object({
+ billingInterval: z.enum(["month", "year"]).nullable(),
+ cancelAtPeriodEnd: z.boolean(),
+ currentPeriodEnd: z.string().nullable(),
+ discount: Schemas$V1AccountListResponseSubscriptionDiscount.out.nullable(),
+ name: z.string().nullable(),
+ price: Schemas$V1AccountListResponseSubscriptionPrice.out,
+ status: z.enum(["active", "past_due"]),
+ })
+ .transform((obj) => {
+ return zodTransform(obj, {
+ billingInterval: "billing_interval",
+ cancelAtPeriodEnd: "cancel_at_period_end",
+ currentPeriodEnd: "current_period_end",
+ discount: "discount",
+ name: "name",
+ price: "price",
+ status: "status",
+ });
+ });
+
+export const Schemas$V1AccountListResponseSubscription = {
+ in: SchemaIn$V1AccountListResponseSubscription,
+ out: SchemaOut$V1AccountListResponseSubscription,
+};
diff --git a/src/types/v1-account-list-response-tier-enum.ts b/src/types/v1-account-list-response-tier-enum.ts
new file mode 100644
index 0000000..a45b1a1
--- /dev/null
+++ b/src/types/v1-account-list-response-tier-enum.ts
@@ -0,0 +1,8 @@
+/**
+ * Subscription tier in effect for the account. `free` if there is no active subscription, including while a subscription is `past_due`.
+ */
+export type V1AccountListResponseTierEnum =
+ | "business"
+ | "creator"
+ | "free"
+ | "pro";
diff --git a/src/types/v1-account-list-response.ts b/src/types/v1-account-list-response.ts
new file mode 100644
index 0000000..254b4d0
--- /dev/null
+++ b/src/types/v1-account-list-response.ts
@@ -0,0 +1,105 @@
+import { zodTransform } from "make-api-request-js";
+import * as z from "zod";
+
+import {
+ External$V1AccountListResponseSubscription,
+ Schemas$V1AccountListResponseSubscription,
+ V1AccountListResponseSubscription,
+} from "./v1-account-list-response-subscription";
+
+/**
+ * V1AccountListResponse
+ */
+export type V1AccountListResponse = {
+ /**
+ * Credits currently available to spend. Includes subscription credits and any purchased credit packs.
+ */
+ credits: number;
+ /**
+ * Email address of the account.
+ */
+ email: string | null;
+ /**
+ * Unique ID of the account that owns the API key.
+ */
+ id: string;
+ /**
+ * Details of the account's subscription plan. `null` if the account has no subscription, e.g. a free account, an account that only purchased credit packs, or an account on usage-based API pricing.
+ *
+ * Reflects the plan currently configured on the subscription. If a plan change is scheduled, `tier` stays on the current plan until the next payment succeeds, so `tier` and `name` can briefly disagree.
+ */
+ subscription: V1AccountListResponseSubscription | null;
+ /**
+ * Subscription tier in effect for the account. `free` if there is no active subscription, including while a subscription is `past_due`.
+ */
+ tier: "business" | "creator" | "free" | "pro";
+};
+
+/**
+ * @internal
+ * V1AccountListResponse without any key transformation, this is what
+ * we expect to come in as network data
+ */
+export type External$V1AccountListResponse = {
+ credits: number;
+ email: string | null;
+ id: string;
+ subscription: External$V1AccountListResponseSubscription | null;
+ tier: "business" | "creator" | "free" | "pro";
+};
+
+/**
+ * Takes network data, validates it, and transforms keys to match typescript object V1AccountListResponse
+ */
+const SchemaIn$V1AccountListResponse: z.ZodType<
+ V1AccountListResponse, // output type of this zod object
+ z.ZodTypeDef,
+ unknown
+> = z
+ .object({
+ credits: z.number().int(),
+ email: z.string().nullable(),
+ id: z.string(),
+ subscription: Schemas$V1AccountListResponseSubscription.in.nullable(),
+ tier: z.enum(["business", "creator", "free", "pro"]),
+ })
+ .transform((obj) => {
+ return zodTransform(obj, {
+ credits: "credits",
+ email: "email",
+ id: "id",
+ subscription: "subscription",
+ tier: "tier",
+ });
+ });
+
+/**
+ * @internal
+ * Takes typescript data, validates it, and maps keys to match the expected external object External$V1AccountListResponse
+ */
+const SchemaOut$V1AccountListResponse: z.ZodType<
+ External$V1AccountListResponse, // output type of this zod object
+ z.ZodTypeDef,
+ V1AccountListResponse // the object to be transformed
+> = z
+ .object({
+ credits: z.number().int(),
+ email: z.string().nullable(),
+ id: z.string(),
+ subscription: Schemas$V1AccountListResponseSubscription.out.nullable(),
+ tier: z.enum(["business", "creator", "free", "pro"]),
+ })
+ .transform((obj) => {
+ return zodTransform(obj, {
+ credits: "credits",
+ email: "email",
+ id: "id",
+ subscription: "subscription",
+ tier: "tier",
+ });
+ });
+
+export const Schemas$V1AccountListResponse = {
+ in: SchemaIn$V1AccountListResponse,
+ out: SchemaOut$V1AccountListResponse,
+};
diff --git a/test/v1-account.test.ts b/test/v1-account.test.ts
new file mode 100644
index 0000000..e78fa57
--- /dev/null
+++ b/test/v1-account.test.ts
@@ -0,0 +1,21 @@
+import { Client, Environment } from "magic-hour";
+
+describe("tests client.v1.account.list", () => {
+ test.concurrent(
+ "GET /v1/account | testId: success_all_params | Success test with response schema validation. Expects status code 200",
+ async () => {
+ const client = new Client({
+ token: "API_TOKEN",
+ environment: Environment.MockServer,
+ });
+ // Get both raw response for status and parsed response for data
+ const [rawResponse, response] = await Promise.all([
+ client.v1.account.list().asResponse(),
+ client.v1.account.list(),
+ ]);
+ expect(rawResponse.status).toBe(200); // Exact status code match
+ // Response body automatically validated by Zod schema during deserialization
+ expect(response).toBeDefined();
+ },
+ );
+});