{"lexicon":1,"id":"money.atmosphere.billing.requestMigrationBatch","defs":{"previewSummary":{"type":"object","required":["source","totalRows","validRows","activeRows","missingEmailRows","duplicateEmailRows","totalAmount","currencies","tierCount"],"properties":{"source":{"type":"string","knownValues":["kofi","substack"],"maxLength":32},"totalRows":{"type":"integer","minimum":0},"validRows":{"type":"integer","minimum":0},"activeRows":{"type":"integer","minimum":0},"stripeRows":{"type":"integer","minimum":0,"description":"Rows whose source payment method was Stripe. Optional: a future source may not distinguish payment methods."},"paypalRows":{"type":"integer","minimum":0,"description":"Rows whose source payment method was PayPal. Optional: a future source may not distinguish payment methods."},"unknownPaymentMethodRows":{"type":"integer","minimum":0},"missingEmailRows":{"type":"integer","minimum":0},"duplicateEmailRows":{"type":"integer","minimum":0},"totalAmount":{"type":"integer","minimum":0},"currencies":{"type":"array","maxLength":20,"items":{"type":"string","minLength":3,"maxLength":3}},"tierCount":{"type":"integer","minimum":0}}},"tierSummary":{"type":"object","required":["tierName","rowCount","activeCount","totalAmount","currencies"],"properties":{"tierName":{"type":"string","maxGraphemes":120,"maxLength":512},"rowCount":{"type":"integer","minimum":0},"activeCount":{"type":"integer","minimum":0},"stripeCount":{"type":"integer","minimum":0,"description":"Rows in this tier whose source payment method was Stripe. Optional: a future source may not distinguish payment methods."},"paypalCount":{"type":"integer","minimum":0,"description":"Rows in this tier whose source payment method was PayPal. Optional: a future source may not distinguish payment methods."},"unknownPaymentMethodCount":{"type":"integer","minimum":0},"totalAmount":{"type":"integer","minimum":0},"currencies":{"type":"array","maxLength":20,"items":{"type":"string","minLength":3,"maxLength":3}}}},"subscriberRow":{"type":"object","description":"One normalized subscriber the app produced from its own export. The app owns source-format parsing and masking; ATM never receives the raw export or raw emails.","required":["active","paymentMethod"],"properties":{"emailHash":{"type":"string","maxLength":128,"description":"Lowercase-hex SHA-256 of the trimmed, lowercased subscriber email — the join key to the Stripe PAN-copy customer mapping at cutover. Omit for a subscriber with no email (ATM flags it)."},"maskedEmail":{"type":"string","maxGraphemes":160,"maxLength":320,"description":"Display-only masked email such as ad*@example.com. Never send the raw email."},"displayName":{"type":"string","maxGraphemes":120,"maxLength":512},"status":{"type":"string","maxLength":128,"description":"Source-native status text, for display/audit only."},"active":{"type":"boolean","description":"Whether the subscription is currently active. The app decides this from its own source semantics."},"paymentMethod":{"type":"string","knownValues":["stripe","paypal","unknown"],"maxLength":32,"description":"Only stripe rows are migratable; paypal/unknown are surfaced for creator review."},"tierName":{"type":"string","maxGraphemes":120,"maxLength":512},"amount":{"type":"integer","minimum":0,"description":"Per-subscriber amount in the currency minor unit. Omit when the amount lives only in Stripe (read at cutover)."},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"Lowercase ISO 4217 currency code."}}},"main":{"type":"procedure","description":"Create a private ATM billing migration review batch from NORMALIZED subscriber rows an app produced from its own export (Ko-fi, Substack, Patreon, …). Source-agnostic: the app owns source-format parsing and masking; ATM's Stripe-to-Stripe migration engine is identical regardless of source. Requires service-auth signed by the originating app DID; the actual Stripe/PAN migration remains a guided ATM review step.","input":{"encoding":"application/json","schema":{"type":"object","required":["creatorDid","rows"],"properties":{"creatorDid":{"type":"string","format":"did"},"rows":{"type":"array","maxLength":50000,"items":{"type":"ref","ref":"#subscriberRow"},"description":"Normalized subscriber rows the app produced from its own export."},"source":{"type":"string","knownValues":["kofi","substack"],"maxLength":64,"description":"Provenance label for the export (Ko-fi, Substack, …). Recorded for audit/display only; it does not change ATM's migration logic."},"environment":{"type":"string","knownValues":["test","live"],"maxLength":8},"dryRun":{"type":"boolean","description":"Preview only: return summary/tiers/warnings WITHOUT persisting a review batch (batch and dashboardUrl are omitted from the response)."},"requestedCutoverAt":{"type":"string","format":"datetime"},"metadata":{"type":"unknown","description":"App-private migration context such as app-local creator/list ids."}}}},"output":{"encoding":"application/json","schema":{"type":"object","required":["summary","tiers","warnings"],"properties":{"dryRun":{"type":"boolean","description":"True when the request was a dry run: no batch was persisted, so batch and dashboardUrl are omitted."},"batch":{"type":"object","required":["id","status","environment","importSource","migrationPath","creatorDid"],"properties":{"id":{"type":"string","maxLength":128},"status":{"type":"string","maxLength":64},"environment":{"type":"string","knownValues":["test","live"],"maxLength":8},"importSource":{"type":"string","knownValues":["kofi","substack"],"maxLength":64},"migrationPath":{"type":"string","maxLength":128},"creatorDid":{"type":"string","format":"did"},"destinationAccountId":{"type":"string","maxLength":128,"description":"The creator's ATM connected-account id — the PAN-copy destination the app surfaces to the creator. Present once the creator has connected an ATM payout account for this environment."},"appDid":{"type":"string","format":"did"},"requestedCutoverAt":{"type":"string","format":"datetime"}}},"dashboardUrl":{"type":"string","format":"uri"},"summary":{"type":"ref","ref":"#previewSummary"},"tiers":{"type":"array","items":{"type":"ref","ref":"#tierSummary"}},"warnings":{"type":"array","items":{"type":"string","maxGraphemes":300,"maxLength":2000}}}}},"errors":[{"name":"AppEnvironmentNotConfigured","description":"This app environment is not configured in ATM."},{"name":"MigrationBatchRequestFailed","description":"The migration review batch could not be created."}]}}}