Welcome to the NL-Dating API documentation. This RESTful API provides comprehensive access to all dating platform features, enabling you to build web and mobile applications that integrate with our backend services.
Production: https://api.nl-dating.com
Development: http://localhost:8000/api
Current Version: v1 (2.17.0)
All responses are returned in JSON format with consistent structure:
{
"success": true,
"message": "Operation completed successfully",
"data": {
// Response data here
}
}
curl -X POST https://api.nl-dating.com/api/mobile/auth/register \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "john@example.com",
"password": "SecurePass123!",
"password_confirmation": "SecurePass123!",
"device_name": "iPhone 14"
}'
curl -X POST https://api.nl-dating.com/api/mobile/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "john@example.com",
"password": "SecurePass123!",
"device_name": "iPhone 14"
}'
curl -X GET https://api.nl-dating.com/api/user/profile \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
The NL-Dating API uses Laravel Sanctum for token-based authentication. Tokens are valid for 7 days by default and can be refreshed using refresh tokens.
sequenceDiagram
participant Client
participant API
participant Database
Client->>API: POST /auth/login
API->>Database: Validate credentials
Database-->>API: User verified
API->>API: Generate tokens
API-->>Client: Access & Refresh tokens
Client->>API: GET /profile (with token)
API->>API: Validate token
API-->>Client: Profile data
POST /api/mobile/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "your-password",
"device_name": "Device Name"
}
Response:
{
"success": true,
"data": {
"access_token": "1|abcdef123456...",
"token_type": "Bearer",
"expires_at": "2025-06-14T10:30:00Z",
"refresh_token": "xyz789...",
"abilities": ["*"]
}
}
POST /api/mobile/auth/refresh
Content-Type: application/json
Authorization: Bearer YOUR_CURRENT_TOKEN
{
"refresh_token": "xyz789..."
}
POST /api/mobile/auth/logout
Authorization: Bearer YOUR_TOKEN
Tokens can have specific abilities that limit their access:
profile:read - Read user profileprofile:write - Update user profilematches:read - View matchesmeetings:manage - Create/update meetingsmessages:send - Send messagespayments:create - Create paymentspremium:access - Access premium features* - Full access (default)API rate limits prevent abuse and ensure fair usage. Limits vary by endpoint and user type.
All responses include rate limit information:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1623456789
| Endpoint Category | Standard User | Premium User | |------------------|---------------|--------------| | Authentication | 5/min | 10/min | | Profile | 100/min | 200/min | | Messaging | 200/min | 400/min | | Discovery | 300/min | 600/min | | Payments | 10/min | 20/min | | Global | 1000/min | 2000/min |
When rate limit is exceeded:
{
"success": false,
"message": "Too many requests. Please try again later.",
"error_code": "RATE_LIMIT_EXCEEDED",
"retry_after": 60
}
| Code | Meaning | Description | |------|---------|-------------| | 200 | OK | Request successful | | 201 | Created | Resource created | | 204 | No Content | Request successful, no content | | 400 | Bad Request | Invalid request data | | 401 | Unauthorized | Invalid/missing authentication | | 403 | Forbidden | Access denied | | 404 | Not Found | Resource not found | | 422 | Unprocessable Entity | Validation failed | | 429 | Too Many Requests | Rate limit exceeded | | 500 | Internal Server Error | Server error |
{
"success": false,
"message": "Validation failed",
"error_code": "VALIDATION_ERROR",
"errors": {
"email": ["The email field is required."],
"age": ["You must be at least 18 years old."]
}
}
AUTHENTICATION_FAILED - Invalid credentialsTOKEN_EXPIRED - Access token expiredVALIDATION_ERROR - Input validation failedRESOURCE_NOT_FOUND - Requested resource doesn't existINSUFFICIENT_PERMISSIONS - Lacking required permissionsRATE_LIMIT_EXCEEDED - Too many requestsPAYMENT_REQUIRED - Premium feature requires paymentMAINTENANCE_MODE - API under maintenancePOST /api/mobile/auth/register
Request Body:
{
"name": "John Doe",
"email": "john@example.com",
"password": "SecurePass123!",
"password_confirmation": "SecurePass123!",
"birth_date": "1990-01-15",
"gender": "male",
"location": "Amsterdam",
"interested_in": "female",
"device_name": "iPhone 14"
}
Response:
{
"success": true,
"data": {
"user": {
"id": 123,
"name": "John Doe",
"email": "john@example.com"
},
"access_token": "1|abcdef...",
"refresh_token": "xyz789..."
}
}
POST /api/mobile/auth/login
POST /api/mobile/auth/logout
Authorization: Bearer YOUR_TOKEN
POST /api/mobile/auth/refresh
GET /api/user/profile
Authorization: Bearer YOUR_TOKEN
Response:
{
"success": true,
"data": {
"id": 123,
"basic_info": {
"full_name": "John Doe",
"age": 35,
"gender": "male",
"location": "Amsterdam",
"biography": "Adventure seeker...",
"profile_photo_url": "https://..."
},
"personal_info": {
"occupation": "Software Engineer",
"education_level": "master",
"height_cm": 180,
"relationship_status": "single",
"has_children": false,
"body_type": "athletic"
},
"lifestyle": {
"smoking_habits": "never",
"drinking_habits": "socially",
"languages_spoken": ["English", "Dutch"]
},
"interests": {
"favorite_music": ["rock", "jazz"],
"favorite_movies": ["action", "comedy"],
"interests": "Travel, Photography, Cooking"
},
"meta": {
"profile_completion": 95,
"is_profile_complete": true,
"quality_score": {
"overall_score": 87.5,
"grade": "A"
},
"is_eligible_for_matching": true
}
}
}
PUT /api/user/profile
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
Request Body:
{
"full_name": "John Michael Doe",
"occupation": "Senior Software Engineer",
"biography": "Passionate about technology and travel...",
"languages_spoken": ["English", "Dutch", "German"]
}
GET /api/user/profile/completion
GET /api/user/profile/quality
PUT /api/user/profile/preferences
Request Body:
{
"interested_in": "female",
"age_range": {"min": 25, "max": 35},
"max_distance": 50,
"looking_for": ["serious_relationship"],
"has_children_preference": "no",
"smoking_preference": "no"
}
PUT /api/user/profile/privacy
GET /api/user/profile/validation-rules
GET /api/user/matches/recent
Query Parameters:
page (integer): Page numberper_page (integer): Items per page (max 50)status (string): Filter by statusResponse:
{
"success": true,
"data": {
"matches": [
{
"id": 456,
"user": {
"id": 789,
"name": "Jane Smith",
"age": 28,
"location": "Amsterdam",
"profile_photo": "https://..."
},
"compatibility_score": 85,
"compatibility_breakdown": {
"basic_preferences": 90,
"lifestyle": 85,
"personality": 88,
"values": 82,
"physical": 80,
"communication": 85,
"dealbreakers": 100
},
"matched_at": "2025-06-07T10:30:00Z",
"last_interaction": "2025-06-07T15:45:00Z"
}
],
"meta": {
"current_page": 1,
"total_pages": 5,
"total_matches": 47
}
}
}
GET /api/user/matches/{matchId}
GET /api/user/matches/statistics
GET /api/user/meetings
GET /api/user/meetings/upcoming
GET /api/user/meetings/{meetingId}
PUT /api/user/meetings/{meetingId}/reschedule
Request Body:
{
"new_date": "2025-06-15",
"new_time": "19:00",
"reason": "Work commitment"
}
DELETE /api/user/meetings/{meetingId}/cancel
GET /api/user/conversations
GET /api/user/messages/{userId}
Query Parameters:
before (timestamp): Get messages before this timelimit (integer): Number of messages (max 100)POST /api/user/messages/send
Request Body:
{
"recipient_id": 789,
"message": "Hello! How are you?",
"type": "text"
}
DELETE /api/user/messages/{messageId}
POST /api/user/messages/mark-read
GET /api/user/payments
POST /api/user/payments
Request Body (multipart/form-data):
meeting_id (required): Meeting IDbank_name (required): Bank nameaccount_holder (required): Account holder nameaccount_number (required): Account numberamount (required): Payment amountpayment_proof (required): Proof file (image/pdf)GET /api/user/payments/info
GET /api/user/safety/blocked
POST /api/user/safety/block
Request Body:
{
"user_id": 999,
"reason": "harassment",
"details": "Inappropriate messages"
}
DELETE /api/user/safety/unblock/{userId}
POST /api/user/safety/report
Request Body:
{
"reported_user_id": 999,
"category": "fake_profile",
"description": "Using stolen photos",
"evidence_urls": ["https://..."],
"urgency": "high"
}
GET /api/user/safety/guidelines
GET /api/discovery/discover
Query Parameters:
latitude (float): User latitudelongitude (float): User longituderadius (integer): Search radius in kmGET /api/discovery/search
Query Parameters:
q (string): Search queryfilters (object): Filter criteriaPOST /api/discovery/like
Request Body:
{
"user_id": 999,
"super_like": false
}
POST /api/discovery/pass
GET /api/user/notifications/counts
GET /api/user/notifications/recent
POST /api/user/notifications/mark-read
Request Body:
{
"notification_ids": [1, 2, 3]
}
// Authentication
class NLDatingAPI {
static let baseURL = "https://api.nl-dating.com/api"
private var token: String?
func login(email: String, password: String) async throws -> AuthResponse {
let url = URL(string: "\(Self.baseURL)/mobile/auth/login")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let body = [
"email": email,
"password": password,
"device_name": UIDevice.current.name
]
request.httpBody = try JSONEncoder().encode(body)
let (data, _) = try await URLSession.shared.data(for: request)
let response = try JSONDecoder().decode(AuthResponse.self, from: data)
self.token = response.data.accessToken
return response
}
func getProfile() async throws -> ProfileResponse {
guard let token = token else {
throw APIError.notAuthenticated
}
let url = URL(string: "\(Self.baseURL)/user/profile")!
var request = URLRequest(url: url)
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
return try JSONDecoder().decode(ProfileResponse.self, from: data)
}
}
// Retrofit Service Definition
interface NLDatingApiService {
@POST("mobile/auth/login")
suspend fun login(@Body request: LoginRequest): AuthResponse
@GET("user/profile")
suspend fun getProfile(@Header("Authorization") token: String): ProfileResponse
@PUT("user/profile")
suspend fun updateProfile(
@Header("Authorization") token: String,
@Body profile: UpdateProfileRequest
): Response<ProfileResponse>
}
// Repository Implementation
class UserRepository(private val api: NLDatingApiService) {
private var authToken: String? = null
suspend fun login(email: String, password: String): Result<User> {
return try {
val response = api.login(
LoginRequest(
email = email,
password = password,
deviceName = Build.MODEL
)
)
authToken = response.data.accessToken
Result.success(response.data.user)
} catch (e: Exception) {
Result.failure(e)
}
}
suspend fun getProfile(): Result<UserProfile> {
return try {
val token = authToken ?: throw UnauthorizedException()
val response = api.getProfile("Bearer $token")
Result.success(response.data)
} catch (e: Exception) {
Result.failure(e)
}
}
}
// API Client
class NLDatingAPI {
constructor() {
this.baseURL = 'https://api.nl-dating.com/api';
this.token = localStorage.getItem('nl_dating_token');
}
async login(email, password) {
const response = await fetch(`${this.baseURL}/mobile/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email,
password,
device_name: 'Web Browser'
})
});
if (!response.ok) {
throw new Error('Login failed');
}
const data = await response.json();
this.token = data.data.access_token;
localStorage.setItem('nl_dating_token', this.token);
return data.data;
}
async getProfile() {
const response = await fetch(`${this.baseURL}/user/profile`, {
headers: {
'Authorization': `Bearer ${this.token}`
}
});
if (response.status === 401) {
// Token expired, try to refresh
await this.refreshToken();
return this.getProfile();
}
return response.json();
}
async updateProfile(profileData) {
const response = await fetch(`${this.baseURL}/user/profile`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(profileData)
});
return response.json();
}
}
// React Hook
function useNLDatingAPI() {
const [api] = useState(() => new NLDatingAPI());
return api;
}
// Component Usage
function ProfileComponent() {
const api = useNLDatingAPI();
const [profile, setProfile] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchProfile() {
try {
const response = await api.getProfile();
setProfile(response.data);
} catch (error) {
console.error('Failed to load profile:', error);
} finally {
setLoading(false);
}
}
fetchProfile();
}, [api]);
if (loading) return <div>Loading...</div>;
if (!profile) return <div>Error loading profile</div>;
return (
<div>
<h1>{profile.basic_info.full_name}</h1>
<p>Age: {profile.basic_info.age}</p>
<p>Location: {profile.basic_info.location}</p>
<p>Profile Completion: {profile.meta.profile_completion}%</p>
</div>
);
}
// API Plugin
export default {
install(app, options) {
const api = {
baseURL: 'https://api.nl-dating.com/api',
token: null,
async request(url, options = {}) {
const config = {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers
}
};
if (this.token) {
config.headers.Authorization = `Bearer ${this.token}`;
}
const response = await fetch(`${this.baseURL}${url}`, config);
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || 'API request failed');
}
return data;
},
async login(credentials) {
const response = await this.request('/mobile/auth/login', {
method: 'POST',
body: JSON.stringify({
...credentials,
device_name: 'Web Browser'
})
});
this.token = response.data.access_token;
return response.data;
},
async getProfile() {
return this.request('/user/profile');
},
async updateProfile(profileData) {
return this.request('/user/profile', {
method: 'PUT',
body: JSON.stringify(profileData)
});
}
};
app.config.globalProperties.$nlDatingAPI = api;
app.provide('nlDatingAPI', api);
}
};
// Component Usage
<template>
<div v-if="profile">
<h1>{{ profile.basic_info.full_name }}</h1>
<p>Profile Completion: {{ profile.meta.profile_completion }}%</p>
</div>
</template>
<script>
import { inject, ref, onMounted } from 'vue';
export default {
setup() {
const api = inject('nlDatingAPI');
const profile = ref(null);
onMounted(async () => {
try {
const response = await api.getProfile();
profile.value = response.data;
} catch (error) {
console.error('Failed to load profile:', error);
}
});
return {
profile
};
}
};
</script>
Configure webhooks to receive real-time updates:
{
"webhook_url": "https://your-app.com/webhooks/nl-dating",
"events": [
"match.created",
"message.received",
"meeting.scheduled",
"payment.verified"
]
}
{
"event": "match.created",
"timestamp": "2025-06-07T10:30:00Z",
"data": {
"match_id": 123,
"user_id": 456,
"matched_user_id": 789,
"compatibility_score": 85
}
}
If you need higher rate limits for your application, contact our support team with:
© 2025 NL-Dating. All rights reserved.