A RESTful API designed to help developers integrate booking functionality into their products. Slouch provides a complete booking management system with project organization, allowing you to manage bookings across multiple projects.
Slouch API enables developers to quickly add booking capabilities to their applications. It handles the core booking logic, data persistence, and provides a clean REST interface for managing bookings and projects.
- Project Management: Organize bookings under projects
- Project Configuration: Configure timezone, booking limits, and allowed time ranges per project
- Booking Management: Create, read, update, and delete bookings with date and time support
- Timezone Support: Automatic timezone conversion - clients can book in any timezone, API stores in project's timezone
- Booking Validation: Enforce max bookings per day and allowed booking time ranges
- Relationship Management: Bookings are automatically associated with projects
- Cascade Deletion: Deleting a project automatically removes all associated bookings and config
- RESTful API: Clean, intuitive endpoints following REST conventions
- OpenAPI Documentation: Auto-generated API documentation for easy integration
- .NET 9.0: Modern C# framework
- PostgreSQL: Robust relational database
- Entity Framework Core: ORM for database operations
- AutoMapper: Object-to-object mapping
- Docker: Containerized PostgreSQL database
- OpenAPI/Swagger: API documentation
The project follows Clean Architecture principles with clear separation of concerns:
Slouch.API/ # API layer (Controllers, Program.cs)
Slouch.Application/ # Application layer (Services, DTOs, Mappings)
Slouch.Domain/ # Domain layer (Entities, Interfaces)
Slouch.Infrastructure/ # Infrastructure layer (Data Access, Repositories)
- .NET 9.0 SDK
- Docker and Docker Compose
- Make (optional, for using Makefile commands)
-
Clone the repository
git clone <repository-url> cd Slouch
-
Start the PostgreSQL database
docker-compose up -d
This starts PostgreSQL on port
5433(to avoid conflicts with local PostgreSQL). -
Update connection string (if needed)
The connection string is configured in
Slouch.API/appsettings.Development.json:{ "ConnectionStrings": { "DefaultConnection": "Host=localhost;Port=5433;Database=slouch_db;Username=slouch_user;Password=slouch_password" } } -
Run database migrations
make migration-apply
Or manually:
dotnet ef database update --project Slouch.Infrastructure --startup-project Slouch.API
-
Run the API
cd Slouch.API dotnet run -
Access the API
- API Base URL:
https://localhost:5001orhttp://localhost:5000 - OpenAPI Documentation:
https://localhost:5001/openapi/v1.json(in development)
- API Base URL:
Manage authentication for the API.
POST /api/auth/github
Content-Type: application/json
{
"gitHubToken": "{Fine-grained Personal Access Token (FGPAT) from GitHub}",
}Manage projects that organize your bookings.
GET /api/projectsGET /api/projects/{id:guid}POST /api/projects
Content-Type: application/json
{
"name": "My Project",
"timeZoneId": "America/New_York",
"maxBookingsPerDay": 10,
"allowedBookingStartTime": "09:00:00",
"allowedBookingEndTime": "17:00:00"
}Note: All config fields are optional. If not provided:
timeZoneIddefaults to "UTC"maxBookingsPerDayis null (unlimited bookings)allowedBookingStartTimeandallowedBookingEndTimeare null (no time restrictions)
Minimal example (config will be created with UTC timezone):
{
"name": "My Project"
}PUT /api/projects/{id:guid}
Content-Type: application/json
{
"id": "guid-here",
"uid": "project-uid",
"name": "Updated Project Name"
}DELETE /api/projects/{id:guid}Note: Deleting a project will cascade delete all associated bookings and configuration.
Configure project-specific settings like timezone, booking limits, and allowed time ranges.
GET /api/projects/{projectId:guid}/configPOST /api/projects/{projectId:guid}/config
Content-Type: application/json
{
"timeZoneId": "America/New_York",
"maxBookingsPerDay": 10,
"allowedBookingStartTime": "09:00:00",
"allowedBookingEndTime": "17:00:00"
}PUT /api/projects/{projectId:guid}/config
Content-Type: application/json
{
"timeZoneId": "America/New_York",
"maxBookingsPerDay": 15,
"allowedBookingStartTime": "08:00:00",
"allowedBookingEndTime": "18:00:00"
}DELETE /api/projects/{projectId:guid}/configNote:
timeZoneIdis required and must be a valid IANA timezone identifier (e.g., "America/New_York", "Europe/London", "Asia/Tokyo")maxBookingsPerDay,allowedBookingStartTime, andallowedBookingEndTimeare optional- A project must have a configuration before bookings can be created
- Bookings are validated against these settings (max bookings per day, allowed time range)
Manage bookings within projects.
GET /api/bookingsGET /api/bookings/{id:guid}POST /api/bookings
Content-Type: application/json
{
"projectId": "project-guid-here",
"name": "John Doe",
"email": "john@example.com",
"phone": "+1234567890",
"date": "2024-01-15T14:30:00+09:00"
}Note:
- The
datefield now accepts ISO 8601 datetime with timezone (e.g.,"2024-01-15T14:30:00+09:00") - Clients can send booking times in any timezone. The API automatically converts the time to the project's configured timezone before storing.
- The booking will be validated against the project's configuration:
- If
maxBookingsPerDayis set, the booking will be rejected if the limit is reached for that date - If
allowedBookingStartTimeandallowedBookingEndTimeare set, the booking time must fall within this range
- If
PUT /api/bookings/{id:guid}
Content-Type: application/json
{
"id": "booking-guid-here",
"projectId": "project-guid-here",
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+1234567890",
"date": "2024-01-16T10:00:00-05:00"
}Note:
- Bookings cannot be moved between projects. The
projectIdin the update request is ignored. - The booking time will be converted to the project's timezone and validated against the project configuration.
DELETE /api/bookings/{id:guid}{
"id": "guid",
"uid": "unique-project-identifier",
"name": "Project Name"
}{
"projectId": "project-guid",
"timeZoneId": "America/New_York",
"maxBookingsPerDay": 10,
"allowedBookingStartTime": "09:00:00",
"allowedBookingEndTime": "17:00:00",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}Fields:
timeZoneId(required): IANA timezone identifier (e.g., "America/New_York", "Europe/London")maxBookingsPerDay(optional): Maximum number of bookings allowed per dayallowedBookingStartTime(optional): Start of allowed booking window (HH:mm:ss format)allowedBookingEndTime(optional): End of allowed booking window (HH:mm:ss format)
{
"id": "guid",
"projectId": "project-guid",
"name": "Customer Name",
"email": "customer@example.com",
"phone": "+1234567890",
"date": "2024-01-15T14:30:00-05:00",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}Note: The date field is now a DateTimeOffset (ISO 8601 format with timezone). Booking times are stored in the project's configured timezone, but clients can send times in any timezone - the API handles the conversion automatically.
make migration-add NAME=YourMigrationNamemake migration-applymake db-up # Start PostgreSQL container
make db-down # Stop PostgreSQL container
make db-reset # Start DB and apply migrations
make db-drop # Drop the database- Slouch.Domain: Core domain entities and interfaces
- Slouch.Application: Business logic, services, DTOs, and AutoMapper profiles
- Slouch.Infrastructure: Data access layer, repositories, and EF Core configuration
- Slouch.API: REST API controllers and application startup
- GUID Primary Keys: All entities use GUID for primary keys
- Snake Case Database: Tables and columns use snake_case naming convention
- Cascade Delete: Deleting a project automatically deletes all its bookings and configuration
- Immutable Project Assignment: Bookings cannot be moved between projects after creation
- Soft Delete Support: BaseEntity includes
DeletedAtfor soft delete capability - Project Configuration: Project-specific settings (timezone, limits, time ranges) are stored in a separate
ProjectConfigentity - Timezone Handling: API automatically converts booking times to the project's timezone, allowing clients worldwide to book without timezone conversion logic
- IANA Timezone Identifiers: Using IANA timezone IDs (e.g., "America/New_York") for better DST handling and cross-platform compatibility
Configure the connection string in appsettings.Development.json or appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Port=5433;Database=slouch_db;Username=slouch_user;Password=slouch_password"
}
}The docker-compose.yml file configures PostgreSQL with:
- Database:
slouch_db - User:
slouch_user - Password:
slouch_password - Port:
5433(mapped from container port 5432)
- Follow the existing code structure and patterns
- Ensure all migrations are applied before committing
- Run linter checks before submitting changes
- Update documentation for any API changes
[Add your license here]
For issues, questions, or contributions, please create an issue or contact the maintainers.