Add AI to a web page

Run your tasks from a page with no server of your own, with a web key that is safe to publish and caps you choose.

A web page can run your tasks directly, with no server of your own. It uses a web key, which starts with dpk_ and is safe to put in the page, because of what it cannot do:

  • It runs only the tasks you allow. It never chooses a model, changes a prompt, or sends tools. The page sends only the input.
  • It works only from the addresses you list.
  • It stops at the caps you set, for the whole key and for each visitor.
  • It reaches nothing else: no files, jobs, webhooks, usage, or settings.

Anyone can copy a web key from your page. What they can do with it is what your page does, up to the same caps. They cannot use it as a general chatbot or spend past your caps. Your organisation pays for every run, as it does for every other call.

Never put an API key, starting with dsk_, in a web page. See API keys.

Before you begin

A task for the page to run, such as support-reply. Its input size, its variables, and the model’s longest answer are what one visitor can send and cost at most.

Make a web key

In the console, open the project, then AI, then Web keys, and select New web key. Give it:

  • A name, such as the site it is for.
  • Addresses, one per line, such as https://shop.example. Use https, and list each subdomain on its own line. Turn on Localhost to try it from http://localhost while you build.
  • Tasks the key may run.
  • Caps:
CapDefaultStops
AI units a day10,000The whole key, until midnight UTC
AI units a month200,000The whole key, until the month ends
AI units a day for each visitor1,000One visitor, until midnight UTC
Runs a minute for each visitor10One visitor, for the rest of the minute
New visits an hour from one network60New visitors from one address, for the rest of the hour

The project’s own AI limits still apply as well. See Usage and limits.

Mobile networks put many people behind one address, so keep the limit on new visits generous. Spending is limited per visitor and per key, not per address.

Run a task from the page

Install the package, or import it from a CDN in a page without a build step:

npm install digitospace
support.ts
import { createSpace } from "digitospace/web"

const space = createSpace({ key: "dpk_…" })

const reply = await space.ai.run("support-reply", {
  input: "My order is late.",
})
document.querySelector("#answer")!.textContent = reply.text

Stream the answer to show it as it is written:

stream.ts
const stream = await space.ai.run("support-reply", {
  input: question,
  stream: true,
})
for await (const chunk of stream) {
  answer.textContent += chunk.text
}

See createSpace() for web pages for every option.

What happens on a visit

  1. The first run starts a visit. The page asks for a small puzzle and solves it, which takes well under a second on most phones and never freezes the page. This makes it costly for a script to pretend to be thousands of visitors.
  2. The page gets a visit that lasts an hour. Later runs use it, and the SDK starts a new one before it ends.
  3. The SDK remembers the visitor in the browser’s storage, so a visitor keeps one daily allowance across reloads. Pass remember: false to keep nothing in the browser.

A visitor’s address is only ever kept as a hash that changes each day.

When a run is refused

Show your visitors a plain message. Every refusal is a SpaceError with a code:

CodeWhat to show or do
visitor_limit_reachedThis visitor has used their allowance. Ask them to try again later
key_limit_reachedYour app has used its allowance for the day or month. Raise the key’s caps if real use reached them
rate_limitedYour app is busy. Try again in a moment
origin_not_allowedThe page’s address is not on the key. Add it in the console
task_not_allowedThe key may not run that task. Allow it in the console
key_not_foundThe key does not exist or was revoked
validation_failedThe input is missing, too long, or not one the task takes
errors.ts
import { createSpace, isSpaceError } from "digitospace/web"

try {
  const reply = await space.ai.run("support-reply", { input })
  show(reply.text)
} catch (error) {
  if (isSpaceError(error) && error.code === "visitor_limit_reached") {
    show("You’ve reached today’s limit. Try again tomorrow.")
  } else throw error
}

Messages from web pages never show your project’s limits or plan.

Watch and change a key

  • Usage shows AI units by web key and by task, so an unusual day stands out.
  • Change a key’s addresses, tasks, or caps at any time. Pages see the change within 30 seconds.
  • Replace a key by making a new one, changing your pages, then revoking the old one. A revoked key stops working within 30 seconds, and cannot be restored.

A project holds up to 20 web keys.

Last updated