API Reference

ReleaseRay provides a REST API for programmatic access to all features. This guide covers authentication, endpoints, rate limits, and code examples.


Overview

Base URL: https://app.releaseray.com/api

Authentication: API keys or OAuth (coming soon)

Format: JSON

Rate Limits: 100 requests per minute per API key


Authentication

API Keys

🔜 Coming in v2.0.0 (April 2026) - API key management is currently in development. This documentation represents the planned functionality.

Generate an API key from your dashboard:

  1. Go to Settings → API Keys
  2. Click "Generate New Key"
  3. Give it a name (e.g., "CI/CD Pipeline")
  4. Copy the key (you won't see it again)

Using API Keys

Include your API key in the Authorization header:

curl https://app.releaseray.com/api/drafts \
  -H "Authorization: Bearer YOUR_API_KEY"

Key Security

  • Store securely: Use environment variables, never commit to git
  • Rotate regularly: Generate new keys every 6 months
  • Limit scope: Create separate keys for different purposes
  • Never share: Each team member should have their own key

Rate Limits

Limits

  • 100 requests per minute per API key
  • 1000 requests per hour per API key
  • 10,000 requests per day per organization

Headers

Check your rate limit status in response headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1699021234

Exceeding Limits

If you exceed rate limits, you'll receive:

{
  "error": "Rate limit exceeded",
  "message": "Limit: 100 requests per minute. Try again in 42 seconds.",
  "retryAfter": 42
}

Response code: 429 Too Many Requests


Endpoints

Drafts

List Drafts

Get all drafts for a release range.

GET /api/drafts?releaseRangeId={rangeId}

Query Parameters:

  • releaseRangeId (required): Release range ID
  • persona (optional): Filter by persona (engineer, internal, customer)

Response:

{
  "drafts": [
    {
      "id": "draft_abc123",
      "releaseRangeId": "range_xyz789",
      "persona": "engineer",
      "bodyMd": "## Features\n- Added OAuth2 support...",
      "flags": {
        "highlights": ["OAuth2 PKCE", "Performance improvement"],
        "contributors": ["johndoe", "janedoe"]
      },
      "createdAt": "2025-11-03T14:32:00Z",
      "updatedAt": "2025-11-03T14:35:00Z"
    }
  ]
}

Get Draft

Get a specific draft by ID.

GET /api/drafts/{draftId}

Response:

{
  "id": "draft_abc123",
  "releaseRangeId": "range_xyz789",
  "persona": "engineer",
  "bodyMd": "## Features\n- Added OAuth2 support...",
  "flags": {
    "highlights": ["OAuth2 PKCE"],
    "upgradeInstructions": "Run `npm install @auth/core@latest`",
    "contributors": ["johndoe"]
  },
  "createdAt": "2025-11-03T14:32:00Z",
  "updatedAt": "2025-11-03T14:35:00Z"
}

Generate Draft

Generate a new draft for a release range.

POST /api/drafts/{rangeId}/generate
Content-Type: application/json

{
  "persona": "engineer"
}

Body Parameters:

  • persona (required): engineer, internal, or customer

Response:

{
  "id": "draft_abc123",
  "status": "processing",
  "estimatedTime": 30
}

Note: Draft generation is async. Poll the draft endpoint to check status.

Update Draft

Edit a draft (manual changes).

PATCH /api/drafts/{draftId}
Content-Type: application/json

{
  "bodyMd": "## Features\n- Added OAuth2 PKCE support (updated)"
}

Response:

{
  "id": "draft_abc123",
  "bodyMd": "## Features\n- Added OAuth2 PKCE support (updated)",
  "updatedAt": "2025-11-03T15:00:00Z"
}

Release Ranges

List Release Ranges

Get all release ranges for a repository.

GET /api/ranges?repoId={repoId}

Query Parameters:

  • repoId (required): Repository ID
  • limit (optional): Number of results (default: 20)
  • offset (optional): Pagination offset (default: 0)

Response:

{
  "ranges": [
    {
      "id": "range_xyz789",
      "repoId": "repo_123",
      "fromTag": "v1.0.0",
      "toTag": "v1.1.0",
      "compareUrl": "https://github.com/owner/repo/compare/v1.0.0...v1.1.0",
      "createdAt": "2025-11-03T10:00:00Z"
    }
  ],
  "total": 45,
  "hasMore": true
}

Get Release Range

Get a specific release range.

GET /api/ranges/{rangeId}

Response:

{
  "id": "range_xyz789",
  "repoId": "repo_123",
  "fromTag": "v1.0.0",
  "toTag": "v1.1.0",
  "compareUrl": "https://github.com/owner/repo/compare/v1.0.0...v1.1.0",
  "prCount": 23,
  "issueCount": 12,
  "createdAt": "2025-11-03T10:00:00Z"
}

Create Release Range

Create a new release range.

POST /api/ranges
Content-Type: application/json

{
  "repoId": "repo_123",
  "fromTag": "v1.1.0",
  "toTag": "v1.2.0"
}

Response:

{
  "id": "range_xyz789",
  "repoId": "repo_123",
  "fromTag": "v1.1.0",
  "toTag": "v1.2.0",
  "compareUrl": "https://github.com/owner/repo/compare/v1.1.0...v1.2.0",
  "createdAt": "2025-11-03T16:00:00Z"
}

Publishing

Publish Draft

Publish a draft to one or more channels.

POST /api/publish
Content-Type: application/json

{
  "draftId": "draft_abc123",
  "channel": "github",
  "draft": false
}

Body Parameters:

  • draftId (required): Draft ID to publish
  • channel (required): github, intercom, hosted, slack, teams
  • draft (optional): Publish as draft (GitHub only, default: false)

Response:

{
  "id": "pub_def456",
  "status": "completed",
  "url": "https://github.com/owner/repo/releases/tag/v1.2.0",
  "publishedAt": "2025-11-03T16:30:00Z"
}

Repositories

List Repositories

Get all connected repositories.

GET /api/repos

Response:

{
  "repos": [
    {
      "id": "repo_123",
      "orgId": "org_456",
      "githubRepoId": 789012,
      "fullName": "acme/myapp",
      "defaultBranch": "main",
      "createdAt": "2025-10-01T08:00:00Z"
    }
  ]
}

Get Repository Tags

Get all Git tags for a repository.

GET /api/repos/{repoId}/tags

Response:

{
  "tags": [
    {
      "name": "v1.2.0",
      "sha": "abc123def456",
      "date": "2025-11-03T10:00:00Z"
    },
    {
      "name": "v1.1.0",
      "sha": "def456ghi789",
      "date": "2025-10-15T14:00:00Z"
    }
  ]
}

Statistics

Get Organization Stats

Get usage statistics for your organization.

GET /api/stats

Response:

{
  "currentMonth": "2025-11",
  "activeRepos": 5,
  "draftsGenerated": 42,
  "publishedReleases": 38,
  "apiCalls": 1234,
  "billingTier": "growth",
  "usagePercentage": 75
}

Error Handling

Error Response Format

All errors follow this format:

{
  "error": "Error type",
  "message": "Human-readable description",
  "details": {
    "field": "Additional context"
  }
}

HTTP Status Codes

  • 200 OK - Success
  • 201 Created - Resource created
  • 400 Bad Request - Invalid request
  • 401 Unauthorized - Missing or invalid API key
  • 403 Forbidden - Insufficient permissions
  • 404 Not Found - Resource not found
  • 429 Too Many Requests - Rate limit exceeded
  • 500 Internal Server Error - Server error

Common Errors

Invalid API Key:

{
  "error": "Unauthorized",
  "message": "Invalid API key. Generate a new key in Settings → API Keys."
}

Rate Limit Exceeded:

{
  "error": "Rate limit exceeded",
  "message": "Limit: 100 requests per minute. Try again in 42 seconds.",
  "retryAfter": 42
}

Resource Not Found:

{
  "error": "Not found",
  "message": "Draft draft_abc123 not found or you don't have access."
}

Code Examples

Node.js

const RELEASERAY_API_KEY = process.env.RELEASERAY_API_KEY;
const BASE_URL = "https://app.releaseray.com/api";

async function generateDraft(rangeId, persona) {
  const response = await fetch(`${BASE_URL}/drafts/${rangeId}/generate`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${RELEASERAY_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ persona }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message);
  }

  return await response.json();
}

// Usage
const draft = await generateDraft("range_xyz789", "engineer");
console.log("Draft generated:", draft.id);

Python

import os
import requests

RELEASERAY_API_KEY = os.getenv('RELEASERAY_API_KEY')
BASE_URL = 'https://app.releaseray.com/api'

def generate_draft(range_id, persona):
    response = requests.post(
        f'{BASE_URL}/drafts/{range_id}/generate',
        headers={
            'Authorization': f'Bearer {RELEASERAY_API_KEY}',
            'Content-Type': 'application/json',
        },
        json={'persona': persona}
    )
    response.raise_for_status()
    return response.json()

# Usage
draft = generate_draft('range_xyz789', 'engineer')
print(f'Draft generated: {draft["id"]}')

cURL

# Generate draft
curl -X POST https://app.releaseray.com/api/drafts/range_xyz789/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"persona": "engineer"}'

# Get draft
curl https://app.releaseray.com/api/drafts/draft_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY"

# Publish to GitHub
curl -X POST https://app.releaseray.com/api/publish \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "draftId": "draft_abc123",
    "channel": "github",
    "draft": false
  }'

Webhooks (Outgoing)

Coming soon: Configure webhooks to receive events when drafts are generated or published.

Event types:

  • draft.generated - Draft generation completed
  • draft.published - Draft published to a channel
  • range.created - New release range created

Webhook payload:

{
  "event": "draft.generated",
  "timestamp": "2025-11-03T16:00:00Z",
  "data": {
    "draftId": "draft_abc123",
    "persona": "engineer",
    "releaseRangeId": "range_xyz789"
  }
}

Pagination

List endpoints support pagination:

GET /api/ranges?repoId=repo_123&limit=20&offset=40

Parameters:

  • limit - Number of results per page (max: 100, default: 20)
  • offset - Number of results to skip (default: 0)

Response includes:

{
  "ranges": [...],
  "total": 150,
  "hasMore": true,
  "nextOffset": 60
}

Filtering & Sorting

Filtering

Filter results with query parameters:

GET /api/drafts?releaseRangeId=range_xyz&persona=engineer

Sorting

Sort results with sort and order:

GET /api/ranges?sort=createdAt&order=desc

Sort fields: createdAt, updatedAt, name
Order: asc, desc


SDKs

Official SDKs

We provide official SDKs for:

  • Node.js/TypeScript - npm install @releaseray/sdk
  • 🔜 Python - Coming Q1 2026
  • 🔜 Go - Coming Q1 2026

Node.js SDK

npm install @releaseray/sdk
import { ReleaseRay } from "@releaseray/sdk";

const client = new ReleaseRay({
  apiKey: process.env.RELEASERAY_API_KEY,
});

// Generate draft
const draft = await client.drafts.generate("range_xyz789", {
  persona: "engineer",
});

// Publish to GitHub
await client.publish({
  draftId: draft.id,
  channel: "github",
});

Best Practices

API Key Management

Do:

  • Store API keys in environment variables
  • Use different keys for dev/staging/production
  • Rotate keys every 6 months
  • Delete unused keys immediately

Don't:

  • Commit API keys to git
  • Share keys between team members
  • Use production keys in development
  • Store keys in plaintext files

Rate Limiting

Do:

  • Implement exponential backoff for retries
  • Cache responses when appropriate
  • Use bulk endpoints when available
  • Monitor rate limit headers

Don't:

  • Retry immediately on 429 errors
  • Poll endpoints more than once per second
  • Make parallel requests for the same data
  • Ignore rate limit warnings

Error Handling

Do:

  • Check HTTP status codes
  • Parse error messages
  • Log errors for debugging
  • Retry on 5xx errors

Don't:

  • Assume all requests succeed
  • Ignore error details
  • Retry on 4xx errors (except 429)
  • Continue on 401/403 errors

Testing

Sandbox Environment

Coming soon: Sandbox API for testing without affecting production data.

Test Mode

Use X-Test-Mode: true header to simulate API calls:

curl https://app.releaseray.com/api/drafts/range_xyz/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Test-Mode: true" \
  -H "Content-Type: application/json" \
  -d '{"persona": "engineer"}'

Test mode:

  • ✅ Validates requests
  • ✅ Returns mock responses
  • ❌ Doesn't consume API credits
  • ❌ Doesn't create actual resources

Changelog

Version 1.0 (Current)

  • Initial API release
  • Drafts CRUD operations
  • Release ranges management
  • Publishing endpoints
  • Statistics endpoint

Upcoming

  • Outgoing webhooks
  • Bulk operations
  • Advanced filtering
  • Custom persona API
  • GraphQL endpoint

Support

Need Help?

Questions about the API? We're here to help!

Report Issues

Found a bug in the API?

  1. Email api@releaseray.com with:
    • Request/response examples
    • Expected vs actual behavior
    • Timestamp of issue
  2. We'll investigate within 24 hours
  3. Critical issues resolved within 4 hours

Related Documentation

We value your privacy

We use cookies to enhance your experience. Essential cookies are required for the site to function. You can choose to accept all cookies or manage your preferences.