Appbricx
Docs
PricingStart free

Start here

OverviewShip your first app with your agentBuild your first app in the browserBuild and change your app in the editor

Build

Describe your app in one fileAdd your own screens and brandUse your data from ReactConnect any MCP clientLet your agent into your workspaceBuild and deploy from your terminalAutomate with the HTTP APIUse your own AI keyWhich AI key is used

Data

What your app runs onREST API for your dataNamed queriesGive each user the right accessEnforce your business rulesFiles and paymentsData templatesKeep secrets safe

Logic

Run work in the backgroundConnect services and schedule jobsLive updatesConnect other appsAdd AI to your app

Sign-in

Let your users sign in

Ship and own

How every release is checkedPublish on a live linkBackups and rollbackUse your own domainTake your code with youRun in your own cloud

End-to-end walkthroughs

Lead intakeMulti-user TodoMulti-tenant SaaSSlack on signup

Developers

Developer guide

Files and payments

Most real apps need users to attach something (a photo of the broken part, a signed PDF, a profile picture) and many need to take money. Both are built in. Uploads are private to the person who made them, and payments never block an order: card when Stripe is connected, pay offline otherwise.

File uploads

What your users get

  • Upload from any form or screen. Image and attachment fields in generated forms already have an upload button.
  • Private by default.Each file belongs to the user who uploaded it. Asking for someone else's file returns "not found", checked in the database before storage is touched.
  • Common types, sensible limits. Images, PDFs, text, audio, video, JSON, ZIP and Office documents, up to 25 MB each by default.

In your own screens

app.upload(file) returns { url, name }. Store the url in an image or attachment field of a row.

async function onPick(e: React.ChangeEvent<HTMLInputElement>) {
  const file = e.target.files?.[0];
  if (!file) return;
  try {
    const { url } = await app.upload(file);
    await app.update("job", jobId, { photo: url });
  } catch (err) {
    setError(err instanceof Error ? err.message : "Upload failed");
  }
}

<input type="file" accept="image/*" onChange={onPick} />

In an offline preview there is no server to store files, so the call rejects with a message. Catch it and show it.

Where files are stored

On Appbricx Cloud, files go to the platform's object store. When you run Appbricx yourself, you choose local disk or any S3-compatible bucket. File records live in your app's own database, so they are covered by backups along with the rest of your data. Uploads appear in the editor under Backend → Logs → Files.

Reference

  • POST /__appbricx/files/sign with { mime, size } returns an upload URL; app.upload does this for you.
  • GET /__appbricx/files/:id redirects the owner to a short-lived signed URL.
  • DELETE /__appbricx/files/:id removes a file.

Payments

How it works

  • Pay offline always works. Pay at pickup or on delivery is the default, so an app is never blocked on a payment provider.
  • Card once you connect Stripe. Add your Stripe credentials in the integrations vault and checkout offers card. Your users pay on Stripe's own checkout page and come back to your app, which confirms with Stripe before the payment counts as paid. No key reaches the browser.
  • The server sets the amount.It recomputes the total from the order's lines and your catalogue prices, so a user cannot change what they pay.
  • Orders are never lost. If Stripe cannot be reached, the order is recorded as an offline payment with a note instead of failing.

Apps with a basket get a checkout step automatically. Payments appear in the editor under Backend → Logs → Payments.

In your own code

const app = useAppHandle();
const methods = await app.pay.methods();          // ["offline"] or ["offline", "card"]
await app.pay.checkout("order", orderId, "card"); // goes to Stripe Checkout

// Back on the page after paying:
useEffect(() => {
  const back = app.pay.returned();                // { status, orderId } or null
  if (back?.status === "success") {
    void app.pay.confirm("order", back.orderId).then(setStatus); // "paid"
  }
}, [app]);

fallback is set when a card payment could not go through and the order was recorded as offline instead. Show the note to the user. See the SDK.

Subscriptions and webhooks. For Stripe events such as a renewed subscription, point a Stripe webhook at a workflow. The multi-tenant SaaS walkthrough shows how.

Related: Frontend SDK · Integrations · Webhooks and schedules

Appbricx

The backend, runtime and hosting for apps your coding agent builds. On our cloud, or run by us in yours.

Product

For coding agentsShowcaseHow it worksCapabilitiesPricingPrivate cloudBYOKFAQ

Resources

DocumentationBlogFor freelancersFor agenciesSupport

Company

ContactPrivate cloud / agencyPrivacyTerms

© 2026 Appbricx. All rights reserved.

TermsPrivacyCookiesAcceptable Use