Skip to content

Web App - User Guide

CodeFetch is a secure, encrypted script library hosted in the cloud. You publish scripts to your private library, retrieve and search them from any machine, and share individual scripts publicly via signed links — all without the server ever seeing your file contents in plaintext.

New to CodeFetch? Start with Getting Started for the full account → extension → CLI walkthrough. This guide documents the web app's underlying API in detail — useful once you're set up and want to script account operations, or understand exactly what a web app button does.


Getting Started

Sign Up

CodeFetch uses email verification — no password required.

  1. Send a signup request:
curl -s -X POST "https://app.codefetch.io/api/request-signup-code" \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com"}'
  1. Check your email for a 6-digit code, then verify it:
curl -s -X POST "https://app.codefetch.io/api/verify-signup-code" \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "code": "123456"}'

The response contains your tenantId and secret:

{
  "ok": true,
  "tenantId": "550e8400-e29b-41d4-a716-446655440000",
  "secret": "base64-encoded-secret"
}

Save both immediately. The secret is returned once only and cannot be recovered — it is never stored on the server. Lose it and you lose access to your library.


Your Two Credentials

Credential What it is When you use it
tenantId Your UUID — identifies your library in every URL Part of every API path
secret Your encryption and authentication key Publishing, deleting, migrating, getting tokens

Set them as shell variables for convenience:

export BASE_URL="https://app.codefetch.io"
export TENANT_ID="550e8400-e29b-41d4-a716-446655440000"
export SECRET="your-secret-here"

Get a Session Token

Most read operations (listing, searching, retrieving files) require a short-lived session token rather than your secret. Tokens expire after 24 hours.

TOKEN=$(curl -s -X POST "${BASE_URL}/${TENANT_ID}/api/auth" \
  -H "Content-Type: application/json" \
  -d "{\"secret\":\"${SECRET}\"}" \
  | grep -o '"token":"[^"]*"' | cut -d'"' -f4)

Use the token as a Bearer header or query parameter:

# Header
-H "Authorization: Bearer ${TOKEN}"

# Query parameter
?token=${TOKEN}

Managing Your Library

Publish a Script

Content must be base64-encoded before sending. Your secret is used directly — no token needed for publishing.

CONTENT=$(base64 -w 0 my-script.sh)   # Linux
# CONTENT=$(base64 -b 0 my-script.sh)  # macOS

curl -s -X POST "${BASE_URL}/${TENANT_ID}/api/publish" \
  -H "Content-Type: application/json" \
  -d "{
    \"id\": \"my-script\",
    \"content\": \"${CONTENT}\",
    \"extension\": \".sh\",
    \"filename\": \"my-script.sh\",
    \"secret\": \"${SECRET}\",
    \"description\": \"My deployment script\",
    \"tags\": [\"deploy\", \"linux\"],
    \"author\": \"Jane\"
  }"
Field Required Notes
id Yes Unique identifier for this script — used in all future operations
content Yes Base64-encoded file content
extension Yes e.g. .sh, .ps1, .py
filename Yes Original filename (display only)
secret Yes Your tenant secret
description No Short summary shown in search results
tags No Array of strings for search filtering
author No Author name

Publishing with an existing id updates the script. If the content has changed, any active shared link for that script is invalidated.


List Your Library

curl -s "${BASE_URL}/${TENANT_ID}/CodeFetch-Library.json?token=${TOKEN}"

Returns a JSON array of all scripts with their metadata — IDs, filenames, tags, descriptions. File content is not included.


Search by Tag

curl -s "${BASE_URL}/${TENANT_ID}/api/search?tags=deploy" \
  -H "Authorization: Bearer ${TOKEN}"

Supply a comma-separated list of tags. Matching is substring-based — dep matches deploy. Omit tags entirely to return all scripts.

# Multiple tags
curl -s "${BASE_URL}/${TENANT_ID}/api/search?tags=deploy,linux" \
  -H "Authorization: Bearer ${TOKEN}"

# All scripts
curl -s "${BASE_URL}/${TENANT_ID}/api/search" \
  -H "Authorization: Bearer ${TOKEN}"

Retrieve a Script

curl -s "${BASE_URL}/${TENANT_ID}/library/my-script.sh?token=${TOKEN}"

Returns the raw encrypted file content. The CodeFetch CLI decrypts this automatically using your secret — if you're calling the API directly you will need to decrypt it client-side.


Update a Filename

To rename a script's display filename without changing its content:

curl -s -X POST "${BASE_URL}/${TENANT_ID}/api/update" \
  -H "Content-Type: application/json" \
  -d "{\"id\": \"my-script\", \"filename\": \"new-name.sh\", \"secret\": \"${SECRET}\"}"

This updates the library metadata only. The script id and stored file are unchanged.


Delete a Script

curl -s -X POST "${BASE_URL}/${TENANT_ID}/api/delete" \
  -H "Content-Type: application/json" \
  -d "{\"id\": \"my-script\", \"secret\": \"${SECRET}\"}"

Removes the file from storage and from the library index. Any shared link for this script will return 404.


Shared links let you share a script publicly — anyone with the link URL can read the content, without needing your secret or a session token.

Shared links use a separate encryption key derived from a signature you control, not your tenant secret. The server stores the content re-encrypted with that signature — it cannot decrypt it without the signature in the URL.

Shared link creation requires the content to be re-encrypted client-side with the share signature before sending. This is handled automatically by the CodeFetch CLI and web frontend. If calling the API directly:

curl -s -X POST "${BASE_URL}/api/create-link" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -d "{
    \"tenantId\": \"${TENANT_ID}\",
    \"scriptPath\": \"library/my-script.sh\",
    \"encryptedContent\": \"<content re-encrypted with signature>\"
  }"

There is one link per script — creating a new link for the same script replaces the previous one.

https://app.codefetch.io/links/{tenantId}/{scriptId}?sig={signature}

No auth required. The sig parameter is the decryption key — without it the content cannot be read.

curl -s "${BASE_URL}/api/list-links" \
  -H "Authorization: Bearer ${TOKEN}"

The response includes an invalidated flag per link. A link becomes invalidated when the script content is updated — the old encrypted content no longer matches. Create a new link to restore sharing.

curl -s -X POST "${BASE_URL}/api/delete-link" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -d "{\"tenantId\": \"${TENANT_ID}\", \"linkToken\": \"my-script\"}"

Quota & Limits

Limit Free Paid (per unit)
File count 3,000 100 per unit
Storage 500 MB 100 MB per unit

File count is checked on new publishes only — updating an existing script does not count against the limit. Storage is tracked incrementally; deleting files frees up quota immediately.

If you hit either limit, publish returns 403 with details of the limit reached.

Free-tier limits and paid pricing are configured server-side and can change — the table above reflects current defaults, not a fixed contractual price. Check Settings → Billing in the web app for your account's actual current limits and any active subscription pricing.


Billing

Paid tiers are managed through Stripe. Open Settings → Billing in the web app to reach the Stripe customer portal, where you can view invoices, update payment details, upgrade or downgrade your tier, and manage or cancel your subscription. Upgrading mid-period is prorated automatically against your current subscription.


Downloads

The web app provides direct download links for the tools that connect to your library:

  • The VS Code extension .vsix (for manual install without the Marketplace — see the VS Code Extension guide)
  • The CLI install scripts for Linux, macOS, and Windows (see the CLI guide)

Changing Your Secret

If you want to rotate your secret, use the migration endpoint. It re-encrypts every file in your library with the new secret in a single operation, with an optional backup.

curl -s -X POST "${BASE_URL}/${TENANT_ID}/api/update-secret" \
  -H "Content-Type: application/json" \
  -d "{
    \"currentSecret\": \"${SECRET}\",
    \"newSecret\": \"myNewSecret456!\",
    \"createBackup\": true
  }"

New secret requirements: 12–128 characters, must contain at least one letter and one number or special character.

With createBackup: true (the default), a copy of all files encrypted with the old secret is kept in your storage under backup/{timestamp}/. This lets you recover if something goes wrong.

The response reports how many files were migrated and how many (if any) failed:

{
  "success": true,
  "migrated": 12,
  "failed": 0,
  "backupsCreated": 12
}

After a successful migration, your old secret no longer works.


Account Management

Change Email

# Step 1 — request a code (sent to your current email)
curl -s -X POST "${BASE_URL}/api/request-email-change-code" \
  -H "Content-Type: application/json" \
  -d "{\"tenantId\": \"${TENANT_ID}\", \"newEmail\": \"new@example.com\"}"

# Step 2 — confirm with the code
curl -s -X POST "${BASE_URL}/${TENANT_ID}/api/change-email" \
  -H "Content-Type: application/json" \
  -d "{\"newEmail\": \"new@example.com\", \"code\": \"123456\", \"secret\": \"${SECRET}\"}"

Delete Your Account

Account deletion is permanent and irreversible — all files and metadata are removed. In the web app this is a single Settings → Delete Account button, which sends you an email confirmation code before actually deleting anything — the two-step API calls below are what that button does under the hood.

# Step 1 — request a deletion code (sent to your email)
curl -s -X POST "${BASE_URL}/api/request-delete-tenant-code" \
  -H "Content-Type: application/json" \
  -d "{\"tenantId\": \"${TENANT_ID}\"}"

# Step 2 — confirm with the code
curl -s -X POST "${BASE_URL}/api/delete-tenant" \
  -H "Content-Type: application/json" \
  -d "{\"tenantId\": \"${TENANT_ID}\", \"code\": \"123456\"}"

Shorty URL Shortener

If you have a Shorty instance, you can configure CodeFetch to register a short URL whenever you create a shared link (e.g. https://codefet.ch/my-script alongside the full shared link URL).

Shorty credentials are stored encrypted on the server — CodeFetch never sees your API key or URL in plaintext.

Configuration is done via the CodeFetch CLI or web frontend, which encrypt the credentials client-side before sending.