Skip to content

API Keys

Authenticate API requests programmatically with API keys.

Overview

API keys enable programmatic access to Open Short URL's API without using session-based authentication. Use them for integrations, automations, and third-party applications.

Creating API Keys

Create an API Key

json
POST /api/api-keys

{
  "name": "Mobile App Integration",
  "expiresAt": "2025-12-31T23:59:59Z"
}

Parameters:

ParameterDescriptionRequiredDefault
nameDescriptive name-
expiresAtExpiration date (ISO 8601)Never

Response:

json
{
  "id": "key_123",
  "name": "Mobile App Integration",
  "key": "osu_a1b2c3d4e5f6g7h8i9j0...",
  "prefix": "osu_a1b2",
  "expiresAt": "2025-12-31T23:59:59Z",
  "createdAt": "2025-01-15T10:00:00Z"
}

WARNING

The full API key is only shown once at creation time. Store it securely!

Using API Keys

Authentication Header

Include the API key in your requests:

Option 1: Bearer Token

Authorization: Bearer osu_a1b2c3d4e5f6g7h8i9j0...

Option 2: X-API-Key Header

X-API-Key: osu_a1b2c3d4e5f6g7h8i9j0...

Example Requests

Create a short URL:

bash
curl -X POST https://api.yourdomain.com/api/urls \
  -H "Authorization: Bearer osu_a1b2c3d4e5f6g7h8..." \
  -H "Content-Type: application/json" \
  -d '{"originalUrl": "https://example.com"}'

Get analytics:

bash
curl https://api.yourdomain.com/api/analytics/overview \
  -H "X-API-Key: osu_a1b2c3d4e5f6g7h8..."

Managing API Keys

List All Keys

GET /api/api-keys

Response:

json
{
  "apiKeys": [
    {
      "id": "key_123",
      "name": "Mobile App Integration",
      "prefix": "osu_a1b2",
      "expiresAt": "2025-12-31T23:59:59Z",
      "createdAt": "2025-01-15T10:00:00Z",
      "lastUsedAt": "2025-01-15T12:30:00Z"
    },
    {
      "id": "key_456",
      "name": "CI/CD Pipeline",
      "prefix": "osu_x9y8",
      "expiresAt": null,
      "createdAt": "2025-01-10T08:00:00Z",
      "lastUsedAt": "2025-01-15T09:15:00Z"
    }
  ],
  "total": 2
}

INFO

Full API keys are never returned after creation. Only the prefix is shown.

Get Single Key

GET /api/api-keys/{id}

Delete Key

DELETE /api/api-keys/{id}

Deleted keys are immediately invalidated.

Key Security

Storage

API keys are stored securely:

  • Hashed using bcrypt
  • SHA-256 index for quick lookup
  • Original key never stored

Key Format

osu_<random-characters>
  • Prefix: osu_ (Open Short URL)
  • Length: ~64 characters total
  • Characters: alphanumeric

Expiration

Keys can be set to expire:

  • Set expiresAt when creating
  • Expired keys return 401 Unauthorized
  • No automatic cleanup (delete manually)

Permissions

API Key Scope

API keys have the same permissions as the user who created them:

User RoleAPI Key Access
AdminFull access to all endpoints
UserAccess to own resources only

Supported Endpoints

All /api/* endpoints support API key authentication:

  • URL management (/api/urls/*)
  • Analytics (/api/analytics/*)
  • Bundles (/api/bundles/*)
  • Webhooks (/api/webhooks/*)
  • A/B Testing (/api/urls/*/variants/*)
  • Routing Rules (/api/urls/*/routing-rules/*)

Rate Limits

OperationLimit
API key creation5 requests/minute
API requests (with key)Same as user limits

Per-User Limits

SettingDefault
Max API keys per user10

Configure via MAX_API_KEYS_PER_USER environment variable.

Best Practices

1. Use Descriptive Names

Name keys based on their purpose:

  • ✅ "Production Backend Server"
  • ✅ "GitHub Actions CI/CD"
  • ❌ "API Key 1"

2. Set Expiration Dates

Use expiring keys when possible:

  • Rotate keys periodically
  • Limit damage from compromised keys
  • Set reasonable lifetimes

3. One Key Per Integration

Create separate keys for each use case:

  • Mobile app → dedicated key
  • CI/CD → dedicated key
  • Third-party service → dedicated key

4. Secure Storage

Never expose keys:

  • Use environment variables
  • Don't commit to version control
  • Use secrets managers in production

Example (Node.js):

javascript
// ✅ Good - from environment
const apiKey = process.env.OPEN_SHORT_URL_API_KEY;

// ❌ Bad - hardcoded
const apiKey = 'osu_a1b2c3d4...';

5. Monitor Usage

Track key usage:

  • Check lastUsedAt regularly
  • Delete unused keys
  • Investigate unexpected activity

6. Rotate Regularly

Periodically replace keys:

  1. Create new key
  2. Update integrations
  3. Delete old key

Error Handling

Authentication Errors

StatusErrorDescription
401UnauthorizedMissing or invalid key
401Key ExpiredAPI key has expired
403ForbiddenKey lacks permission

Example Error Response

json
{
  "statusCode": 401,
  "message": "Invalid API key",
  "error": "Unauthorized"
}

Integration Examples

Node.js

javascript
const axios = require('axios');

const client = axios.create({
  baseURL: 'https://api.yourdomain.com',
  headers: {
    'Authorization': `Bearer ${process.env.API_KEY}`
  }
});

// Create short URL
const response = await client.post('/api/urls', {
  originalUrl: 'https://example.com/page'
});

Python

python
import requests

headers = {
    'Authorization': f'Bearer {os.environ["API_KEY"]}',
    'Content-Type': 'application/json'
}

response = requests.post(
    'https://api.yourdomain.com/api/urls',
    headers=headers,
    json={'originalUrl': 'https://example.com/page'}
)

cURL

bash
export API_KEY="osu_a1b2c3d4..."

curl -X POST https://api.yourdomain.com/api/urls \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"originalUrl": "https://example.com/page"}'

Use Cases

CI/CD Integration

Automate URL creation in deployment pipelines:

yaml
# GitHub Actions example
- name: Create Short URL for Deploy
  run: |
    curl -X POST ${{ secrets.API_URL }}/api/urls \
      -H "Authorization: Bearer ${{ secrets.API_KEY }}" \
      -H "Content-Type: application/json" \
      -d '{"originalUrl": "${{ env.DEPLOY_URL }}", "customSlug": "deploy-${{ github.sha }}"}'

Mobile App

Create dynamic links from your app:

swift
// Swift example
let request = URLRequest(url: apiURL)
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")

Backend Service

Integrate with your existing systems:

javascript
// Express middleware
app.post('/share', async (req, res) => {
  const shortUrl = await createShortUrl(req.body.url);
  res.json({ shortUrl });
});

Next Steps

Released under the MIT License.