API Reference

    Programmatically create and manage short links with the Weeny API.

    Base URL: https://weeny.app

    All endpoints under /api/v1 require API key authentication and return JSON.

    Authentication

    Create an API key in Workspace Settings → API Keys, then send it on every request:

    x-api-key: wn_your_api_key_here
    

    Or as a Bearer token:

    Authorization: Bearer wn_your_api_key_here
    

    Keys are scoped to a single workspace. Requests only see and mutate links in that workspace.

    CORS

    Browser clients can call the API from any origin. Allowed headers include Content-Type, Authorization, x-api-key, and x-workspace-id.


    Links

    List links

    GET /api/v1/links
    

    Returns a paginated list of links in the authenticated workspace.

    Query parameters

    ParameterTypeDefaultDescription
    pagenumber1Page number (minimum 1)
    limitnumber10Page size (maximum 100)
    searchstringFilter by title, short URL, or destination URL
    statusstringallall, active, or inactive
    tagstringFilter links that include this tag
    sortBystringcreatedAtcreatedAt, updatedAt, title, or clicks
    sortOrderstringdescasc or desc

    Example request

    curl "https://weeny.app/api/v1/links?page=1&limit=10&status=active" \
      -H "x-api-key: wn_your_api_key_here"
    

    Example response

    {
      "data": [
        {
          "id": "clx...",
          "title": "Campaign landing",
          "shortUrl": "abc123",
          "originalUrl": "https://example.com/landing",
          "isActive": true,
          "expiresAt": null,
          "tags": ["campaign", "spring"],
          "password": { "isProtected": false },
          "utm": {
            "source": "newsletter",
            "medium": "email",
            "campaign": "spring-sale",
            "term": null,
            "content": null
          },
          "meta": {
            "title": null,
            "url": null,
            "description": null
          },
          "domainId": null,
          "domain": null,
          "clicks": 42,
          "uniqueVisitors": 30,
          "publicAnalytics": false,
          "createdAt": "2026-07-01T12:00:00.000Z",
          "updatedAt": "2026-07-02T09:30:00.000Z"
        }
      ],
      "pagination": {
        "page": 1,
        "limit": 10,
        "totalCount": 1,
        "totalPages": 1,
        "hasNextPage": false,
        "hasPreviousPage": false
      }
    }
    

    Create a link

    POST /api/v1/links
    

    Creates a new short link. Subject to your plan’s active links limit.

    Request body

    FieldTypeRequiredDescription
    originalUrlstringYesDestination URL
    titlestringNoDisplay title
    shortUrlstringNoCustom slug. Auto-generated if omitted
    utmobjectNoUTM params: source, medium, campaign, term, content
    passwordobjectNo{ "isProtected": true, "password": "secret" } to lock the link
    expiresAtstringNoISO 8601 expiry datetime
    tagsstring[]NoTags for organization and filtering
    metaTitlestringNoOpen Graph / social title
    metaUrlstringNoOpen Graph / social image URL
    domainstringNoCustom domain hostname (must belong to the workspace)
    domainIdstringNoCustom domain ID (must belong to the workspace)
    publicAnalyticsbooleanNoWhether public analytics are enabled (default false)

    If both domain and domainId are provided, they must refer to the same custom domain.

    Example request

    curl -X POST "https://weeny.app/api/v1/links" \
      -H "Content-Type: application/json" \
      -H "x-api-key: wn_your_api_key_here" \
      -d '{
        "originalUrl": "https://example.com/landing",
        "title": "Campaign landing",
        "shortUrl": "spring",
        "tags": ["campaign"],
        "utm": {
          "source": "newsletter",
          "medium": "email",
          "campaign": "spring-sale"
        }
      }'
    

    Example response (201)

    {
      "data": {
        "id": "clx...",
        "title": "Campaign landing",
        "shortUrl": "spring",
        "originalUrl": "https://example.com/landing",
        "isActive": true,
        "expiresAt": null,
        "tags": ["campaign"],
        "password": { "isProtected": false },
        "utm": {
          "source": "newsletter",
          "medium": "email",
          "campaign": "spring-sale",
          "term": null,
          "content": null
        },
        "meta": {
          "title": null,
          "url": null,
          "description": null
        },
        "domainId": null,
        "domain": null,
        "clicks": 0,
        "uniqueVisitors": 0,
        "publicAnalytics": false,
        "createdAt": "2026-07-18T12:00:00.000Z",
        "updatedAt": "2026-07-18T12:00:00.000Z"
      }
    }
    

    Get a link

    GET /api/v1/links/{identifier}
    

    Fetches a single link by ID or short URL slug within the workspace.

    Example request

    curl "https://weeny.app/api/v1/links/spring" \
      -H "x-api-key: wn_your_api_key_here"
    

    Example response

    {
      "data": {
        "id": "clx...",
        "title": "Campaign landing",
        "shortUrl": "spring",
        "originalUrl": "https://example.com/landing",
        "isActive": true,
        "expiresAt": null,
        "tags": ["campaign"],
        "password": { "isProtected": false },
        "utm": {
          "source": "newsletter",
          "medium": "email",
          "campaign": "spring-sale",
          "term": null,
          "content": null
        },
        "meta": {
          "title": null,
          "url": null,
          "description": null
        },
        "domainId": null,
        "domain": null,
        "clicks": 42,
        "uniqueVisitors": 30,
        "publicAnalytics": false,
        "createdAt": "2026-07-18T12:00:00.000Z",
        "updatedAt": "2026-07-18T12:00:00.000Z"
      }
    }
    

    Errors

    Error responses use this shape:

    {
      "error": "Human-readable message",
      "details": {}
    }
    
    StatusMeaning
    400Invalid request (missing fields, invalid URL, bad datetime, etc.)
    401Missing or invalid API key
    403Plan limit reached (e.g. active links)
    404Link or custom domain not found
    409Short URL already taken on that domain
    500Unexpected server error

    When the active links limit is exceeded, details may include:

    {
      "code": "ACTIVE_LINKS_LIMIT_EXCEEDED",
      "plan": "starter",
      "limit": 100,
      "currentCount": 100
    }
    

    Getting started

    1. Sign in to Weeny and open your workspace settings.
    2. Create an API key under API Keys.
    3. Call GET /api/v1/links or POST /api/v1/links with your key.
    4. Need help? Contact us or visit the Help Center.

    We use cookies to enhance your experience.