X3DStudios

Account and billing

Signing up and signing in, what each plan costs and includes, managing a subscription and card, where invoices live, and how to get your data out.

An account is an email, a username and a password. It holds your generation credits, your plan, your orders and — if you use the print API — a card on file. This page covers every way in, what each plan actually includes, how to change or cancel a subscription, where the receipts are, and what you can and cannot do about your data.

Creating an account#

Registration is one form at /auth/signup and then a six-digit code by email. The code is what turns a registered account into one that can sign in, so nothing is usable until you enter it.

  1. 1
    Register

    Name, username, email, password and password confirmation. All five are required, and the two passwords have to match.

  2. 2
    Enter the code we email you

    Six digits, valid for 10 minutes. Five wrong attempts destroy the code and you have to request a new one. A code can be re-sent, but only three verification emails go to one address in any 15 minutes.

  3. 3
    You are signed in

    Verifying creates your credit balance with 5 free generation credits and signs you in through the same password provider you would use next time.

POST/api/auth/signupNo auth

One endpoint, three actions: register, verify, resend.

curl -X POST https://x3dstudios.com/api/auth/signup \
  -H "Content-Type: application/json" \
  -d '{
    "action": "register",
    "name": "Ada Lovelace",
    "username": "ada_l",
    "email": "[email protected]",
    "password": "correct-horse-battery",
    "confirmPassword": "correct-horse-battery"
  }'
# => {"step":"verify","email":"[email protected]"}
FieldRule
EmailThe identity of the account, stored lowercased. One account per address.
Username3 to 20 characters, lowercase letters, digits and underscores only. Must be unused.
PasswordAt least 8 characters. Stored as a salted scrypt hash, never in plain text.
An unverified account cannot sign in
Sign-in refuses an account that has never entered its code, and gives the same generic failure as a wrong password. If a fresh account will not log in, the code is usually the reason — request a new one from the signup screen.

Signing in#

There is exactly one sign-in method: a password. The first field accepts either your username or your email address, so whichever you remember works. Sign in at /auth/login; /auth/signin redirects there. A session lasts 30 days, and signing out from /profile ends it on that device only.

Forgot the password: /auth/forgot-password emails a six-digit code, and the second step takes that code plus a new password of at least 8 characters. The first step answers the same way whether or not the address has an account, so it cannot be used to find out who has one.

POST/api/auth/reset-passwordNo auth

action "send-code" emails a code; action "reset" takes email, code and the new password.

Changing a username or password while signed in is done from /profile, or directly against the profile endpoint. Changing a password requires the current one.

PATCH/api/profileSigned in

Send username, or currentPassword plus newPassword. GET returns name, username, email and createdAt.

Plans#

Two subscriptions exist, both monthly, both cancellable at any time. Every account, plan or not, starts with 5 generation credits. Generation credits and print credit are separate balances: credits are spent generating models, print credit is a dollar amount that comes off a print order.

No planMakerPro Studio
Price$0$19 / month$49 / month
Generation credits5 to start, then buy packs100 each month400 each month
Print creditNone$5 each month$10 each month
Print discountNoneNone10% off Print & Ship orders

The credits arrive when each monthly invoice is paid, granted once per invoice, so a retry or a duplicate webhook cannot double-grant. Cancelling clears the plan and its print credit as soon as Stripe reports the subscription ended; generation credits already in your balance stay there.

Where the Pro discount applies
The 10% is applied by the Print & Ship checkout at /print, on the quoted total before print credit is taken off. That total already has the $7 postage folded into it, so the discount comes off the parcel as well as the print. It is not applied to a basket checked out from the cart.

The Enterprise card on /pricing is a conversation, not a plan you can buy — checkout accepts only maker and pro. Use /contact for dedicated capacity, bulk SLAs or white-label API terms.

Credit packs#

Credits can be bought outright without a subscription. A pack tops up the same balance a plan grants into.

PackCreditsPricePer credit
small60$10$0.17
medium150$22$0.15
large400$50$0.13
POST/api/billing/checkoutSigned in

Opens a Stripe Checkout session for a subscription or a credit pack.

Body
typestringrequired
Anything else is a 400. Print orders are explicitly rejected here — they go through /api/print-order so the price is calculated from the stored model.subscriptioncredit_topup
planstringoptional
Required when type is subscription.makerpro
packstringoptional
Required when type is credit_topup.smallmediumlarge

The response is { url, sessionId } — send the customer to url. Without a session the endpoint returns 401, and if payments are not configured it returns 503 rather than a broken checkout page.

Changing a plan or a payment method#

Upgrades, downgrades, cancellation and card changes all happen in the Stripe billing portal rather than in a form here, so card details never touch this site. Ask for a portal link and open it.

POST/api/billing/manageSigned in

Returns { url } for a Stripe billing portal session that comes back to /pricing.

An account with no Stripe customer id on record answers 400 with "No active subscription found. Please subscribe first." Only a subscription writes that id: a credit pack is a one-off payment and the card saved for the print API is held separately, so neither of those opens the portal. Subscribe once and it opens from then on.

Receipts, invoices and statements#

There are three places money is shown, and each answers a different question.

  • Payment History on /orders — your last 50 Stripe charges with the amount, date, status and a Receipt link straight to Stripe's hosted receipt. The list is charges only; a refund shows up in Stripe's receipt rather than as its own row.
  • /orders/statement — a printable statement for any date range, defaulting to the range you have filtered on the orders page. It lists date, order, items and amount, totals them, and shows anything not charged (cancelled, refunded, failed) in a separate list rather than hiding it. Issued as Xpress 3D Print, Austin, Texas. There is no PDF library behind it: the Print / Save as PDF button uses your browser's print dialog, with the page furniture hidden.
  • The Stripe billing portal, via /api/billing/manage — subscription invoices and their payment status.
Statement totals are summed in cents
Every line is added as an integer number of cents and divided once at the end, so a hundred orders cannot drift a penny away from what was charged.

A card on file for the print API#

Orders submitted through the developer print API are charged automatically on submission, so a saved card is a precondition for having a key at all. Both live on /profile.

  1. 1
    Add the card

    The Add a card on file button opens a Stripe-hosted setup page and returns you to /profile#api. Nothing is charged when you save it.

  2. 2
    Generate the key

    The plaintext key is shown exactly once — copy it then. Afterwards only its prefix is displayed, because only a hash is stored. Generating again rotates the key and invalidates the old one.

  3. 3
    Revoke when you are done

    The revoke button clears the key immediately. Any request using it fails from that moment.

POST/api/account/api-keySigned in

Creates or rotates the print API key. Returns 402 with code CARD_REQUIRED when no card is on file.

The card status endpoint reports the brand, last four digits and expiry of the saved card, which is what the badge on /profile reads. Connected Chrome extensions carry a separate token type and are revoked separately, individually or all at once. See /docs/api/keys and /docs/integrations/chrome-extension.

Getting your data out, and closing the account#

Being straight about this: there is no delete-my-account button and no one-click export. What exists is the following, and anything beyond it is a person at [email protected].

  • Order history: /orders lists your last 50 orders, and /orders/statement turns any date range into a document you can save as a PDF.
  • Payment records: each charge has a Stripe receipt link, and subscription invoices sit in the billing portal.
  • Credentials: change your username or password at /profile at any time.
  • Access: revoke the API key from /profile, and sign out there to end the session on a device. A connected extension is revoked with POST /api/extension/revoke from a signed-in browser — /profile has no extension section yet.
  • Deletion: email [email protected] from the account's address. Financial records attached to completed orders are kept for accounting.