A Laravel-based example implementation of the Contact Bridge API for synchronizing contact data between systems. This project demonstrates secure API communication using HMAC-SHA256 authentication, incremental data synchronization, and efficient pagination patterns.
- Contact Synchronization: API endpoints for syncing contact data between applications
- Incremental Sync Support: Efficient data synchronization using
modified_sincetimestamps - Pagination: Built-in pagination for large datasets
- API Discovery: Self-documenting endpoints
- Secure Authentication: HMAC-SHA256 request/response signing
- Test Client: Reference implementation included
- Framework: Laravel 12
- PHP: 8.2+
- Database: SQLite
- Authentication: HMAC-SHA256
- PHP 8.2 or higher
- Composer
- Git
-
Clone the repository
git clone <repository-url> cd php-hmac-example
-
Install dependencies
composer install
-
Create environment file
cp .env.example .env
-
Generate application key
php artisan key:generate
-
Run migrations and seed the database
php artisan migrate --seed
This will create:
- SQLite database with
contactsandapi_clientstables - Test API client with predictable credentials
- 500 sample contacts for testing
- SQLite database with
-
Start the development server
composer run dev
This runs both the Laravel development server and real-time log viewer concurrently.
Alternatively, run just the server:
php artisan serve
-
Test the API
php tests/hmac-test-client.php
All tests should return HTTP 200 responses. See
tests/hmac-test-client.phpfor the test client implementation.
After setup, the API is available at http://localhost:8000/api.
Default Test Credentials (from database/seeders/ApiClientSeeder.php):
- Access Key:
ak_test_1234567890 - Secret Key:
sk_test_secret_key_1234567890
Example Request: See tests/hmac-test-client.php for a complete reference implementation of HMAC signature generation and verification.
GET /api/contact-bridge
Purpose: API discovery and configuration
Response:
{
"endpoints": {
"index": "http://localhost:8000/api/contact-bridge/index",
"contacts": "http://localhost:8000/api/contact-bridge/data"
},
"api_version": "v1",
"client_minimum_version": "0.0.0"
}GET /api/contact-bridge/index?page=1
Purpose: Lightweight listing of contact IDs
Features:
- Pagination: 100 contacts per page
- Returns contact IDs in
crm-{id}format
Query Parameters:
page(optional): Page number (default: 1)
Response:
{
"contacts": ["crm-1", "crm-2", "crm-3", ...],
"total": 500,
"has_more": true
}GET /api/contact-bridge/data?page=1&modified_since=2024-01-15T10:30:00Z
Purpose: Full contact data retrieval with change tracking
Features:
- Pagination: 25 contacts per page
- Incremental sync support
- Ordered by modification date (newest first)
Query Parameters:
page(optional): Page number (default: 1)modified_since(optional): ISO 8601 timestamp for incremental sync
Response:
{
"contacts": [
{
"id": "crm-234",
"first_name": "John",
"last_name": "Doe",
"phone": "+1-234-567-8900",
"group": "Business",
"tag": "VIP",
"notes": "Notes for John Doe",
"modified_at": "2024-01-15T14:30:00+00:00"
}
],
"total": 500,
"has_more": true
}The demo:shuffle command (app/Console/Commands/DemoShuffleCommand.php) simulates real-world data changes for testing incremental synchronization:
php artisan demo:shuffleWhat it does:
- Deletes 10-30% of existing contacts randomly
- Updates 20-40% of remaining contacts with new random values
- Creates new contacts to replace deleted ones (±20% variance)
Why it's useful:
- Test the
modified_sinceparameter on/api/contact-bridge/dataendpoint - Verify your client properly handles data deletions, updates, and additions
- Simulate real-world data synchronization scenarios
Recommended workflow:
- Run initial sync with your client application
- Run
php artisan demo:shuffle - Run incremental sync using
modified_sincetimestamp from step 1 - Verify your client detected all changes
The core security component is the VerifyHmacSignature middleware.
Implementation: app/Http/Middleware/VerifyHmacSignature.php
Registration (bootstrap/app.php):
->withMiddleware(function (Middleware $middleware): void {
$middleware->alias([
'hmac.verify' => \App\Http\Middleware\VerifyHmacSignature::class,
]);
})What it does:
- Validates incoming request signatures using HMAC-SHA256
- Signs outgoing responses with HMAC-SHA256
- Includes query parameters in signature to prevent tampering
- Uses access key + secret key authentication
Signature Format:
METHOD
PATH
CANONICAL_QUERY_PARAMS (sorted alphabetically)
TIMESTAMP
BODY_HASH (SHA-256)
Required Request Headers:
X-Access-Key: Your API access keyX-Timestamp: Unix timestampX-HMAC-Signature: Base64-encoded HMAC signature
Response Headers:
X-Response-HMAC-Signature: Server's signature of the response
All controllers are located in app/Http/Controllers/ and registered in routes/api.php with the hmac.verify middleware.
File: app/Http/Controllers/ContactBridgeConfigController.php
- Route:
GET /api/contact-bridge - Purpose: API discovery endpoint
- Returns: Available endpoints, API version, client requirements
- Use Case: Entry point for clients to discover the API
File: app/Http/Controllers/ContactBridgeIndexController.php
- Route:
GET /api/contact-bridge/index - Purpose: Efficient contact ID listing
- Pagination: 100 contacts per page
- Query Parameters:
page(optional, default: 1) - Returns: Contact IDs in
crm-{id}format, total count, pagination flag - Use Case: Lightweight endpoint to check which contacts exist
File: app/Http/Controllers/ContactBridgeDataController.php
- Route:
GET /api/contact-bridge/data - Purpose: Full contact data retrieval with change tracking
- Pagination: 25 contacts per page
- Query Parameters:
page(optional, default: 1)modified_since(optional, ISO 8601 timestamp for incremental sync)
- Returns: Complete contact details with modification timestamps
- Use Case: Sync full contact data, supports incremental updates
Route Registration (routes/api.php):
Route::middleware('hmac.verify')->group(function () {
Route::get('/contact-bridge', ContactBridgeConfigController::class)
->name('contact-bridge.config');
Route::get('/contact-bridge/index', ContactBridgeIndexController::class)
->name('contact-bridge.index');
Route::get('/contact-bridge/data', ContactBridgeDataController::class)
->name('contact-bridge.contacts');
});This is an API-only Laravel application implementing the Contact Bridge API specification. Built with no web routes, sessions, or views, it demonstrates:
- Contact Bridge API endpoints for data synchronization
- RESTful API design patterns
- Incremental sync using modification timestamps
- Secure authentication with HMAC-SHA256
- Pagination strategies for large datasets
- HMAC-SHA256 Signatures: Cryptographic verification of all requests and responses
- Query Parameter Signing: Prevents tampering with URL parameters
- Timestamp Validation: Protects against replay attacks
- Access Key Authentication: Client identification and authorization
- Canonical Query Parameters: Consistent signature generation regardless of parameter order
The included test client (tests/hmac-test-client.php) demonstrates proper HMAC signature implementation:
php tests/hmac-test-client.phpWhat it tests:
- Basic endpoint discovery
- Pagination on both index and data endpoints
- Query parameter signing
- Incremental sync with
modified_since - Request and response signature verification
All tests should return HTTP 200 responses with valid HMAC signatures.
MIT License - see composer.json
This project demonstrates:
- Contact Synchronization APIs: Building efficient contact data sync endpoints
- Data Synchronization: Efficient incremental sync patterns using timestamps
- API Security: HMAC-SHA256 authentication for secure API communication
- Laravel Architecture: Modern Laravel API-only application development
- RESTful Design: Clean, predictable API structure
Perfect for teams building contact synchronization features or integrating contact management systems between applications.