Jump to section
Skipline API Referencev1
The Skipline REST API lets you interact with your waitlist campaigns programmatically. Add signups from your own frontend, fetch your waitlist to display in your app, look up individual subscribers, and pull campaign stats — all with a simple HTTP API.
The Skipline API is currently in beta. Endpoints and response shapes may change. We will announce breaking changes with at least 14 days notice.
Authentication
All API requests must be authenticated with an API key. Pass your key in the Authorization header as a Bearer token.
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxYou can generate API keys from your Skipline dashboard under Settings → API Keys. Keys start with sk_live_. Each key is shown only once when created — store it somewhere safe immediately.
Never expose your API key in client-side JavaScript or public repositories. Always make API calls from your server.
Example Request
curl https://skipline.tech/api/v1/campaign \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx" \
-G \
--data-urlencode "slug=my-product"Base URL
All API endpoints are relative to the following base URL:
https://skipline.tech/api/v1All requests and responses use JSON. Include the Content-Type: application/json header on all POST requests.
Rate Limiting
The API is rate limited to 100 requests per 60 seconds per API key. Rate limit information is returned in the response headers on every request.
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests allowed per window (always 100) |
| X-RateLimit-Remaining | Requests remaining in the current window |
| X-RateLimit-Reset | Unix timestamp in milliseconds when the window resets |
When you exceed the rate limit the API returns a 429 Too Many Requests response. Wait until the X-RateLimit-Reset time before retrying.
{
"error": "Rate limit exceeded. Try again after 1704067260000",
"code": "RATE_LIMITED"
}Errors
Skipline uses standard HTTP status codes. All error responses include a human-readable error message and a machine-readable code string.
| Code | HTTP Status | Description |
|---|---|---|
| UNAUTHORIZED | 401 | Missing or invalid API key |
| FORBIDDEN | 403 | Valid key but wrong account for this resource |
| NOT_FOUND | 404 | The requested resource does not exist |
| VALIDATION_ERROR | 400 | Missing or invalid request parameters |
| CONFLICT | 409 | Resource already exists (e.g. duplicate email) |
| RATE_LIMITED | 429 | Too many requests |
| INTERNAL_ERROR | 500 | Something went wrong on our end |
Example Error Response
{
"error": "This email is already on the waitlist",
"code": "CONFLICT"
}GET /signups
/api/v1/signupsFetch all signups for a campaignReturns a paginated list of all signups for a campaign ordered by position ascending by default.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| campaign_id | string | one of these two is required | UUID of the campaign |
| slug | string | one of these two is required | Slug of the campaign (alternative to campaign_id) |
| page | integer | optional | Page number, default 1 |
| limit | integer | optional | Results per page, default 50, max 500 |
| sort | string | optional | Sort field: position, created_at, referral_count. Default: position |
| order | string | optional | asc or desc. Default: asc |
Example Request
curl https://skipline.tech/api/v1/signups \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx" \
-G \
--data-urlencode "slug=my-product" \
--data-urlencode "limit=10" \
--data-urlencode "sort=referral_count" \
--data-urlencode "order=desc"Example Response
{
"data": {
"signups": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "jane@example.com",
"position": 1,
"referral_count": 14,
"ref_code": "jane42",
"referred_by": null,
"is_early_access": true,
"anon_name": "Silent Fox",
"anon_emoji": "🦊",
"created_at": "2026-01-12T08:32:00Z"
}
],
"pagination": {
"total": 847,
"page": 1,
"limit": 10,
"total_pages": 85,
"has_next": true,
"has_prev": false
}
},
"meta": {
"campaign_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2026-01-12T09:00:00Z"
}
}The anon_name and anon_emoji fields are generated deterministically from the signup id. The same signup always gets the same name. These are the values shown on the public waitlist leaderboard.
POST /signups
/api/v1/signupsAdd someone to the waitlistAdds a new signup to your waitlist. Triggers the referral mechanic if a ref_code is provided. Sends a confirmation email to the new signup and a referral notification email to the referrer.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| campaign_id | string | one of these two is required | UUID of the campaign |
| slug | string | one of these two is required | Slug of the campaign |
| string | required | Email address of the person joining | |
| ref_code | string | optional | Referral code of the person who referred them. Triggers referral mechanics. |
Example Request
curl -X POST https://skipline.tech/api/v1/signups \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"slug": "my-product",
"email": "newuser@example.com",
"ref_code": "jane42"
}'Example Response (201 Created)
{
"data": {
"signup": {
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"email": "newuser@example.com",
"position": 423,
"ref_code": "new99x",
"referral_count": 0,
"is_early_access": false,
"created_at": "2026-01-12T09:05:00Z"
}
},
"meta": {
"campaign_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2026-01-12T09:05:00Z"
}
}Possible Errors
| Status | Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR | Email is missing or invalid format |
| 409 | CONFLICT | Email is already on this waitlist |
| 404 | NOT_FOUND | Campaign not found |
GET /signups/:email
/api/v1/signups/:emailLook up a specific signupReturns the signup record for a specific email address including their current queue position, referral count, and a ready-to-share referral link.
The email address must be URL-encoded in the path. For example, user@example.com becomes user%40example.com.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | required | URL-encoded email address of the signup |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| campaign_id | string | one of these two is required | UUID of the campaign |
| slug | string | one of these two is required | Slug of the campaign |
Example Request
curl "https://skipline.tech/api/v1/signups/jane%40example.com" \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx" \
-G \
--data-urlencode "slug=my-product"Example Response
{
"data": {
"signup": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "jane@example.com",
"position": 1,
"referral_count": 14,
"ref_code": "jane42",
"referred_by": null,
"is_early_access": true,
"anon_name": "Silent Fox",
"anon_emoji": "🦊",
"referral_link": "https://skipline.tech/w/my-product?ref=jane42",
"created_at": "2026-01-12T08:32:00Z"
}
},
"meta": {
"campaign_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2026-01-12T09:10:00Z"
}
}DELETE /signups/:email
/api/v1/signups/:emailRemove someone from the waitlistPermanently removes a signup from the waitlist. Also deletes all referral records associated with this signup. This action cannot be undone.
Deleting a signup also removes their referral history. The positions of other signups are not automatically recalculated after deletion.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | required | URL-encoded email address of the signup to delete |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| campaign_id | string | one of these two is required | UUID of the campaign |
| slug | string | one of these two is required | Slug of the campaign |
Example Request
curl -X DELETE "https://skipline.tech/api/v1/signups/jane%40example.com" \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx" \
-G \
--data-urlencode "slug=my-product"Example Response
{
"data": {
"deleted": true,
"email": "jane@example.com"
},
"meta": {
"campaign_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2026-01-12T09:15:00Z"
}
}GET /campaign
/api/v1/campaignFetch campaign statsReturns campaign details and computed analytics stats including total signups, referral count, viral coefficient, and referral conversion rate.
The viral coefficient is the average number of referrals per active referrer. A coefficient above 1.0 means your waitlist is growing virally — each referrer brings in more than one new signup on average.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| campaign_id | string | one of these two is required | UUID of the campaign |
| slug | string | one of these two is required | Slug of the campaign |
Example Request
curl https://skipline.tech/api/v1/campaign \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx" \
-G \
--data-urlencode "slug=my-product"Example Response
{
"data": {
"campaign": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "My Product Launch",
"slug": "my-product",
"headline": "The AI tool your team has been waiting for",
"is_live": true,
"created_at": "2026-01-01T00:00:00Z"
},
"stats": {
"total_signups": 847,
"total_referrals": 312,
"referral_conversion_rate": 36.8,
"viral_coefficient": 1.43,
"early_access_unlocked": 24,
"top_position": 1,
"signups_who_shared": 218
}
},
"meta": {
"campaign_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2026-01-12T09:20:00Z"
}
}API Keys
API keys are generated from your Skipline dashboard under Settings → API Keys. Each key belongs to your account and has access to all campaigns under that account.
- Keys start with
sk_live_followed by 64 random hex characters - Each key is shown only once at creation — copy it immediately
- You can generate multiple keys and name them (e.g. “Production”, “Staging”)
- Delete keys you no longer need from the dashboard
- Keys do not expire but can be revoked at any time
SDKs & Examples
No official SDK yet — the API is simple enough to use with plain fetch or any HTTP client. Here are ready-to-use examples.
// Add someone to your waitlist
const response = await fetch('https://skipline.tech/api/v1/signups', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
slug: 'my-product',
email: 'user@example.com',
ref_code: 'abc123' // optional
})
})
const { data } = await response.json()
console.log(`Added to waitlist at position #${data.signup.position}`)
console.log(`Their referral link: /w/my-product?ref=${data.signup.ref_code}`)Changelog
v1.0
Initial API release
REST API launched with five endpoints: GET /signups, POST /signups, GET /signups/:email, DELETE /signups/:email, GET /campaign. API key authentication with SHA-256 hashing. Rate limiting at 100 requests per 60 seconds.