Sniply API
Overview
Sniply API is a modern, production‑ready backend service for storing, searching, and managing text and code snippets. It is designed with a strong focus on simplicity, performance, and clean architecture, making it suitable for personal tools, developer platforms, or integration into larger systems.
The project follows best practices commonly found in high‑quality open‑source backend repositories: clear domain boundaries, explicit configuration, containerized workflows, and first‑class API documentation.
At runtime, all traffic flows through Traefik (TLS + routing), the API talks to PostgreSQL, and observability is handled via OpenTelemetry + Grafana (Prometheus, Loki, Tempo).
Key Features
- Session‑based authentication (HttpOnly cookies)
- API keys with scoped access (
read,write,read_write) - User management (signup, login, profile management)
- Full CRUD for snippets
- Snippet visibility control (
public/private) - Advanced search using PostgreSQL Full‑Text Search and pg_trgm (fuzzy search)
- Filtering by language, tags, and visibility
- Pagination support
- Redis‑backed snippet cache and login rate limiting
- OpenAPI / Swagger documentation
- Docker‑first development and deployment
- Ready for observability (metrics, logs, traces)
Tech Stack
| Category | Technology |
|---|---|
| Language | Go |
| HTTP Router | chi |
| Database | PostgreSQL 18 |
| Cache / Sessions | Redis |
| Search | Full‑Text Search + pg_trgm |
| Migrations | golang-migrate |
| Containerization | Docker, Docker Compose |
| API Docs | Swagger / OpenAPI |
| Proxy | Traefik |
| Observability | OpenTelemetry + Grafana (Prometheus, Loki, Tempo, Alloy) |
For more details and flow diagrams, see here
Getting Started
Prerequisites
Make sure you have the following installed:
- Go 1.24 or newer
- Docker and Docker Compose
- PostgreSQL 18 (or run via Docker)
Installation
Clone the Repository
git clone https://github.com/PabloPavan/_api.git
cd _apiRunning with Docker (Recommended)
For development, debugging, and advanced Docker workflows (including debug images and troubleshooting), please refer to README.dev.md. That document describes the recommended and correct way to run Sniply API with Docker in development environments.
API Overview
Health Check
Returns service health status.
Authentication
Login
POST /v1/auth/login Content-Type: application/json { "email": "user@example.com", "password": "password" }
Response:
Sets a Set-Cookie header with the HttpOnly session cookie.
{
"session_expires_at": "2025-01-01T00:00:00Z",
"csrf_token": "..."
}For state-changing requests using the session cookie, send X-CSRF-Token with the value returned on login.
API Keys
Authenticated endpoints (except login/logout) also accept API keys.
Create an API key (requires session auth + CSRF token):
POST /v1/auth/api-keys X-CSRF-Token: <csrf_token> { "name": "ci", "scope": "read_write" }
Response returns the key once:
{
"id": "key_...",
"token": "sk_...",
"token_prefix": "sk_...",
"scope": "read_write"
}Use the API key:
GET /v1/snippets X-API-Key: sk_...
Scopes: read allows GET/HEAD/OPTIONS; write allows POST/PUT/PATCH/DELETE; read_write allows both.
API keys are stored only as hashes; the raw token is not persisted and is shown once at creation.
Logout
Clears the session cookie.
API Keys (session only)
| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/auth/api-keys |
Create API key |
| GET | /v1/auth/api-keys |
List API keys |
| DELETE | /v1/auth/api-keys/{id} |
Revoke API key |
Users
| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/users |
Create a new user |
| GET | /v1/users/me |
Get current user |
| PUT | /v1/users/me |
Update current user |
| DELETE | /v1/users/me |
Delete current user |
All /me endpoints require authentication.
| Method | Endpoint | Description |
|---|---|---|
| GET | /v1/snippets |
List snippets with filters |
| GET | /v1/snippets/{id} |
Get snippet by ID |
| POST | /v1/snippets |
Create a snippet |
| PUT | /v1/snippets/{id} |
Update a snippet |
| DELETE | /v1/snippets/{id} |
Delete a snippet |
Query Parameters (List)
q– search term (full‑text / fuzzy)language– filter by languagetags– filter by tagsvisibility–publicorprivatelimit– pagination sizeoffset– pagination offset
Example – Create Snippet
POST /v1/snippets { "name": "Hello World", "content": "print('Hello, world!')", "language": "python", "tags": ["example", "demo"], "visibility": "public" }
Security Considerations
- All protected endpoints require a valid session cookie
- Sessions use HttpOnly cookies (avoid localStorage tokens)
- Session requests that change data require
X-CSRF-Token - Passwords are stored hashed
- Always run behind HTTPS in production
- Validate environment variables before startup
Session Configuration
Session behavior is controlled by three environment variables:
SESSION_TTL– sliding window duration for active sessionsSESSION_REFRESH_BEFORE– refresh the session when it is within this window of expirySESSION_MAX_AGE– hard close absolute limit since login
Project Structure (High Level)
src/
cmd/ # Application entrypoints
internal/ # Application core (domain, services, repositories)
migrations/ # Database migrations
observability/ # Grafana/Prometheus/Loki/Tempo configs
compose.base.yml # Base Docker Compose
compose.dev.yml # Development overrides
compose.prod.yml # Production overrides
Dockerfile
Contributing
Contributions are welcome.
Recommended workflow:
- Fork the repository
- Create a feature branch (
feature/my-feature) - Commit with clear messages
- Add tests when applicable
- Open a Pull Request with a clear description
Roadmap
- Automated tests (unit and integration)
- CI pipeline (lint, test, build)
- API quotas
- Extended observability dashboards
- Deployment examples (Kubernetes, cloud providers)
License
This project is licensed under the MIT License. See the LICENSE file for details.
Author
Developed by Pablo Pavan.