---
name: create-shortcut
description: Create a Lora shortcut — a memorable, one-word link that resolves any destination URL inside a workspace, with optional metadata (title, expiration, password, masked URL) and country/platform routing. Use when a user wants to create, register, or publish a shortcut in their Lora workspace.
---

# Create a Lora shortcut

## What a shortcut is

A Lora shortcut maps a short, memorable handle (e.g. `handbook`, `team/onboarding`) to a destination URL. It lives inside a workspace, behind a login, and can carry metadata (title, description, expiration, password, masked URL, platform overrides, geo routing). Think of it as one-word access to knowledge — not a public link shortener.

The shareable URL is `https://app.uselora.com/short/<slug>`, where `<slug>` is 1–50 chars and may contain `/` (e.g. `team/handbook` → `https://app.uselora.com/short/team/handbook`). The `lor.cx` host is only used inside generated QR codes — never as a sharing URL.

## When to use this skill

Trigger when a user wants to create a shortcut **in their own Lora workspace**. Common phrasing: "create a shortcut for X", "make `foo` point to Y", "register `team/handbook` for the Notion page", "set up a shortcut that routes by country".

Do **not** use this skill to "shorten any URL" for anonymous visitors — Lora's API is per-workspace and requires authentication.

## Prerequisites

- The user must have a Lora workspace and an API key with the `shortcuts.write` scope. Keys are created at **Profile > API Keys**. Format: `lora_sk_…`. If the user doesn't have a key, direct them there first.
- The destination URL must use one of: `http(s)`, `mailto:`, `tel:`, `sms:`, or an app deep-link scheme (e.g. `notion://`, `slack://`). `javascript:`, `data:`, and `file:` are rejected.

## Endpoint

`POST https://api.uselora.com/v1/shortcuts`

Headers:

- `Authorization: Bearer lora_sk_…`
- `Content-Type: application/json`
- `Idempotency-Key: <uuid>` — optional; pass the same key on retries so a transient failure doesn't create duplicates.

## Minimum request

```bash
curl https://api.uselora.com/v1/shortcuts \
  -H "Authorization: Bearer $LORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "handbook",
    "destination": "https://www.notion.so/example/our-handbook"
  }'
```

Response: HTTP 201 with the created shortcut. Share `https://app.uselora.com/short/handbook`.

## Useful optional fields

| Field         | When to set it                                                          |
| ------------- | ----------------------------------------------------------------------- |
| `title`       | Human-readable label shown in the dashboard and OG previews.            |
| `description` | Supporting copy for previews and search.                                |
| `expiresAt`   | ISO 8601 future timestamp. Visitors hit a 404 after.                    |
| `password`    | Plaintext on write; visitors must enter it before redirect.             |
| `masked`      | `true` hides the destination in the browser address bar.                |
| `folderId`    | Place into a specific folder (defaults to workspace default folder).    |
| `tagIds`      | Array of 8-char tag short IDs for categorization.                       |
| `ios`         | iOS-only destination. See **Country and platform routing** below.       |
| `android`     | Android-only destination. See **Country and platform routing** below.   |
| `geo`         | Country-keyed destination map. See **Country and platform routing** below. |

## Country and platform routing

When `ios`, `android`, or `geo` are set, each visit is resolved in this order:

1. Visitor on iOS and `ios` set → use `ios`.
2. Visitor on Android and `android` set → use `android`.
3. Visitor's country matches a key in `geo` → use that destination.
4. Otherwise → fall back to `destination`.

`destination` is always required and acts as the catch-all. There is no per-country iOS/Android map — platform overrides apply globally.

`geo` is an object keyed by **ISO-3166-1 alpha-2** country codes (e.g. `US`, `DE`, `GB`, `JP`). Values are full destination URLs with the same scheme rules as `destination`. Casing is normalised server-side, so `us` works too. Unsupported codes are dropped silently. Each country may appear only once per shortcut — duplicates after normalisation produce a `validation_error`.

Example combining all three:

```bash
curl https://api.uselora.com/v1/shortcuts \
  -H "Authorization: Bearer $LORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "app",
    "destination": "https://example.com/download",
    "ios": "https://apps.apple.com/app/id000000000",
    "android": "https://play.google.com/store/apps/details?id=com.example",
    "geo": {
      "DE": "https://example.de/download",
      "FR": "https://example.fr/download"
    }
  }'
```

Visitor from Germany on Android → Android URL (rule 2). Germany on desktop → German URL (rule 3). Spain on desktop → fallback `destination` (rule 4).

Notes:

- Geo detection is best-effort. VPN/proxy visitors may bypass routing.
- `PATCH /v1/shortcuts/{slug}` **replaces** the full `geo` map. To add one country, send the existing map plus the new key. To clear all geo rules, send `"geo": null`.

## Error handling

Errors return JSON `{ error, code?, requestId, fieldErrors? }`. Map `code` to action:

| Status | `code`                | What to do                                                                                 |
| ------ | --------------------- | ------------------------------------------------------------------------------------------ |
| 400    | `validation_error`    | `fieldErrors` lists the offending fields. Fix and retry.                                   |
| 400    | `reserved_slug`       | Slug is on Lora's reserved list. Pick another.                                             |
| 401    | —                     | Key is missing, malformed, expired, or unscoped. 401 is intentionally opaque.              |
| 403    | `insufficient_scope`  | Key lacks `shortcuts.write`. `required_scope` names the missing scope.                     |
| 404    | `folder_not_found`    | `folderId` doesn't exist in this workspace. Drop it or fix the ID.                         |
| 404    | `tag_not_found`       | One or more `tagIds` are invalid. Remove or correct.                                       |
| 409    | `slug_conflict`       | A shortcut with this slug exists. Pick another, or upsert with `PUT /v1/shortcuts/{slug}`. |
| 429    | `rate_limit_exceeded` | Honour `Retry-After`. Don't hammer the API.                                                |
| 500    | `internal_error`      | Safe to retry with backoff. Reuse the `Idempotency-Key`.                                   |

## Related

- Full API reference: <https://uselora.dev>.
