This commit is contained in:
sjdonado
2025-11-02 10:00:09 +00:00
commit f5fa372379
9 changed files with 558 additions and 0 deletions
View File
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

+51
View File
@@ -0,0 +1,51 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body
{
margin:0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script>
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
configUrl: "swagger-config.json",
dom_id: '#swagger-ui'
})
// End Swagger UI call region
window.ui = ui
}
</script>
</body>
</html>
+496
View File
@@ -0,0 +1,496 @@
openapi: 3.1.0
info:
title: Bit - URL Shortener API
description: A high-performance URL shortener service with click tracking and analytics
version: 1.0.0
contact:
name: API Support
url: https://github.com/sjdonado/bit
servers:
- url: http://localhost:4000
description: Development server
- url: http://localhost:4001
description: Benchmark server
security:
- ApiKeyAuth: []
paths:
/api/ping:
get:
summary: Ping the API
description: Health check endpoint to verify the API is running
operationId: ping
tags:
- Health
security: []
responses:
'200':
description: API is healthy
content:
application/json:
schema:
type: object
properties:
data:
type: string
example: pong
/{slug}:
get:
summary: Redirect by slug
description: Redirects to the original URL and tracks the click asynchronously
operationId: redirectBySlug
tags:
- Redirects
security: []
parameters:
- name: slug
in: path
required: true
description: The short URL slug
schema:
type: string
example: 3wP4BQ
- name: utm_source
in: query
required: false
description: UTM source parameter for tracking
schema:
type: string
example: email_campaign
responses:
'301':
description: Redirect to original URL
headers:
Location:
description: The original URL
schema:
type: string
example: https://example.com
X-Forwarded-For:
description: Client IP address
schema:
type: string
User-Agent:
description: User agent string
schema:
type: string
'404':
description: Link not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/links:
get:
summary: List all links
description: Retrieve all links for the authenticated user with pagination support
operationId: listLinks
tags:
- Links
parameters:
- name: limit
in: query
description: Number of results per page
schema:
type: integer
default: 100
minimum: 1
maximum: 1000
- name: cursor
in: query
description: Pagination cursor from previous response
schema:
type: string
responses:
'200':
description: List of links
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/LinkSummary'
pagination:
$ref: '#/components/schemas/Pagination'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
summary: Create new link
description: Create a new shortened link
operationId: createLink
tags:
- Links
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- url
properties:
url:
type: string
format: uri
description: The URL to shorten
example: https://example.com
responses:
'201':
description: Link created successfully
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/Link'
'400':
description: Bad request - invalid URL or missing field
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
missingField:
value:
error: "url: Required field"
invalidUrl:
value:
errors:
url:
- is invalid
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/links/{id}:
get:
summary: Get link by ID
description: Retrieve a specific link with up to 100 most recent clicks. For complete click history, use /api/links/{id}/clicks
operationId: getLink
tags:
- Links
parameters:
- name: id
in: path
required: true
description: Link ID
schema:
type: integer
format: int64
responses:
'200':
description: Link details
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/Link'
'404':
description: Link not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
summary: Update link
description: Update the URL of an existing link
operationId: updateLink
tags:
- Links
parameters:
- name: id
in: path
required: true
description: Link ID
schema:
type: integer
format: int64
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- url
properties:
url:
type: string
format: uri
description: The new URL
example: https://newexample.com
responses:
'200':
description: Link updated successfully
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/Link'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - link belongs to another user
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Link not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
summary: Delete link
description: Delete a link and all its associated clicks
operationId: deleteLink
tags:
- Links
parameters:
- name: id
in: path
required: true
description: Link ID
schema:
type: integer
format: int64
responses:
'204':
description: Link deleted successfully
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - link belongs to another user
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Link not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/links/{id}/clicks:
get:
summary: List clicks for a link
description: Retrieve all clicks for a specific link with pagination support
operationId: listClicks
tags:
- Clicks
parameters:
- name: id
in: path
required: true
description: Link ID
schema:
type: integer
format: int64
- name: limit
in: query
description: Number of results per page
schema:
type: integer
default: 100
minimum: 1
maximum: 1000
- name: cursor
in: query
description: Pagination cursor from previous response
schema:
type: string
responses:
'200':
description: List of clicks
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Click'
pagination:
$ref: '#/components/schemas/Pagination'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Link not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-Api-Key
description: API key for authentication
schemas:
LinkSummary:
type: object
properties:
id:
type: integer
format: int64
description: Unique link identifier
example: 1
refer:
type: string
format: uri
description: The shortened URL
example: http://localhost:4000/3wP4BQ
origin:
type: string
format: uri
description: The original URL
example: https://monocuco.donado.co
Link:
allOf:
- $ref: '#/components/schemas/LinkSummary'
- type: object
properties:
clicks:
type: array
description: Array of click records (up to 100 most recent)
items:
$ref: '#/components/schemas/Click'
Click:
type: object
properties:
id:
type: integer
format: int64
description: Unique click identifier
example: 1
user_agent:
type: string
description: User agent string
example: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:127.0) Gecko/20100101 Firefox/127.0
country:
type: string
nullable: true
description: Country code (ISO 3166-1 alpha-2)
example: US
browser:
type: string
nullable: true
description: Browser name
example: Firefox
os:
type: string
nullable: true
description: Operating system
example: Mac OS X
referer:
type: string
nullable: true
description: Referer domain or utm_source
example: Direct
created_at:
type: string
format: date-time
description: Click timestamp
example: 2024-07-12T19:25:22Z
Pagination:
type: object
properties:
has_more:
type: boolean
description: Whether there are more results
example: true
next:
type: integer
format: int64
nullable: true
description: Cursor for next page (link/click ID)
example: 12
Error:
type: object
properties:
error:
type: string
description: Error message
example: Resource not found
required:
- error
ValidationErrors:
type: object
properties:
errors:
type: object
additionalProperties:
type: array
items:
type: string
description: Field-level validation errors
example:
url:
- is invalid
tags:
- name: Health
description: Health check endpoints
- name: Redirects
description: URL redirection and click tracking
- name: Links
description: Link management operations
- name: Clicks
description: Click analytics and tracking
+1
View File
@@ -0,0 +1 @@
{"url":"openapi.yaml","deepLinking":true}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4
View File
File diff suppressed because one or more lines are too long