Sign in

Uselss Store developer API

Publish the weird little thing.

Use a personal key to publish from your own script, Codex, Claude, or a terminal. Your key belongs in an environment variable, never pasted into an agent prompt.

01 / Create a key

Sign in once, then automate.

Create a named personal key in settings. It is shown once, lasts 90 days, and you can revoke it at any time. Each account can have up to 10 active keys.

02 / CLI

Use the tiny Node CLI.

Use Node.js 22 or newer. Save your app details in app.json using the example below, and save a cover image. Set the store URL and your key in your shell, validate, then publish. HTTPS is required except for loopback development. Include links: {} when the app has no links.

export USELSS_STORE_URL="https://maximumeffort.lol" export USELSS_API_KEY="usl_your_secret" curl --fail -O "$USELSS_STORE_URL/cli/uselss.mjs" node uselss.mjs publish app.json --image cover.png --dry-run node uselss.mjs publish app.json --image cover.png node uselss.mjs get mood-clock-v1 node uselss.mjs unpublish mood-clock-v1 node uselss.mjs republish mood-clock-v1 node uselss.mjs delete mood-clock-v1 --confirm

03 / HTTP API

One stable ID per app.

PUT /api/v1/apps/{externalId} accepts multipart form data: an app JSON field and an image file. An image is required on the first publish and optional on an update. Reuse an external ID to update the same app without changing its slug. Editing an unpublished app keeps it unpublished.

export USELSS_STORE_URL="https://maximumeffort.lol" export USELSS_API_KEY="usl_your_secret" curl --fail-with-body -X PUT "$USELSS_STORE_URL/api/v1/apps/mood-clock-v1" \ -H "Authorization: Bearer $USELSS_API_KEY" \ -F 'app={"name":"Mood Clock","tagline":"Time, but moody.","description":"A small clock that changes its face based on a completely arbitrary feeling.","links":{"website":"https://example.com/mood-clock"}};type=application/json' \ -F "image=@cover.png;type=image/png"

Read your app and status

curl --fail-with-body \ -H "Authorization: Bearer $USELSS_API_KEY" \ "$USELSS_STORE_URL/api/v1/apps/mood-clock-v1"

04 / Lifecycle

Step away, come back, or close it forever.

Use PATCH with the action unpublish or republish. Both actions are idempotent and preserve original publication and reaction timestamps. Moderated apps cannot be republished.

curl --fail-with-body -X PATCH "$USELSS_STORE_URL/api/v1/apps/mood-clock-v1" \ -H "Authorization: Bearer $USELSS_API_KEY" \ -H "Content-Type: application/json" \ --data '{"action":"unpublish"}'

DELETE permanently removes app content, reactions, and image references, then retains a minimal identity tombstone. The external ID can never be reused or resurrected.

curl --fail-with-body -X DELETE "$USELSS_STORE_URL/api/v1/apps/mood-clock-v1" \ -H "Authorization: Bearer $USELSS_API_KEY"

Manifest

Fields and responses.

The manifest uses externalId, name, tagline, description, optional story, platform, version, and optional validated links: website, repository, release, appStore, android, and demo. The HTTP API accepts omitted links; the CLI requires an empty links: {} when there are none. Success is 201 for a new app or 200 for an update: {app: {id, externalId, slug, url}, created}. Reads and lifecycle responses include status: published, unpublished, deleted, hidden, or removed. Errors use {error: {code, message}}.

Requests are limited to 60 per minute per account. Relevant errors are 400, 401, 403, 404, 410, 413, 415, 429, and 503.

Cover images

A screenshot is enough.

Use a static PNG, JPEG or WebP up to 5 MiB, 16 megapixels and 8192 pixels per side. We resize images and remove location metadata. Each account can upload 5 images per minute and 50 per day, store 100 MiB of images and publish 100 apps. Keep installers on GitHub Releases and submit the link.

Copy for an agent

Let your agent take it from here.

Read https://maximumeffort.lol/llms.txt and publish this app using the local Uselss Store CLI. Use USELSS_STORE_URL and USELSS_API_KEY already present in the environment; do not request, print, persist, or paste either value. Use a stable externalId, include links: {} if there are no links, and run --dry-run before publishing.