This guide will help you get started with the NL-Dating API in just a few minutes.
Development Environment
http://localhost:8000/apiProduction Environment
https://api.nl-dating.comNL-Dating-API.postman_collection.jsonbase_url: http://localhost:8000/apiaccess_token: (will be set automatically after login)# Test the API is working
curl http://localhost:8000/api/health
# Create your first user
curl -X POST http://localhost:8000/api/mobile/auth/register \
-H "Content-Type: application/json" \
-d '{
"name": "Test Developer",
"email": "dev@example.com",
"password": "SecurePass123!",
"password_confirmation": "SecurePass123!",
"birth_date": "1990-01-01",
"gender": "male",
"location": "Amsterdam",
"interested_in": "female",
"device_name": "Developer Test"
}'
// JavaScript Example
const response = await fetch('http://localhost:8000/api/mobile/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'dev@example.com',
password: 'SecurePass123!',
device_name: 'My App'
})
});
const data = await response.json();
const token = data.data.access_token; // Save this!
// Always include the token in your requests
const profile = await fetch('http://localhost:8000/api/user/profile', {
headers: {
'Authorization': `Bearer ${token}`
}
});
Here's a complete example of fetching and displaying a user profile:
import React, { useState, useEffect } from 'react';
function UserProfile() {
const [profile, setProfile] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchProfile();
}, []);
const fetchProfile = async () => {
try {
const token = localStorage.getItem('nl_dating_token');
const response = await fetch('http://localhost:8000/api/user/profile', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
throw new Error('Failed to fetch profile');
}
const data = await response.json();
setProfile(data.data);
} catch (error) {
console.error('Error:', error);
} finally {
setLoading(false);
}
};
if (loading) return <div>Loading...</div>;
if (!profile) return <div>Error loading profile</div>;
return (
<div className="profile">
<img src={profile.basic_info.profile_photo_url} alt="Profile" />
<h1>{profile.basic_info.full_name}</h1>
<p>Age: {profile.basic_info.age}</p>
<p>Location: {profile.basic_info.location}</p>
<div className="progress">
Profile Completion: {profile.meta.profile_completion}%
</div>
</div>
);
}
import 'package:http/http.dart' as http;
import 'dart:convert';
class ProfileService {
final String baseUrl = 'http://localhost:8000/api';
String? _token;
Future<Map<String, dynamic>> getProfile() async {
final response = await http.get(
Uri.parse('$baseUrl/user/profile'),
headers: {
'Authorization': 'Bearer $_token',
},
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
return data['data'];
} else {
throw Exception('Failed to load profile');
}
}
}
// Usage in Widget
class ProfileScreen extends StatelessWidget {
final ProfileService _service = ProfileService();
@override
Widget build(BuildContext context) {
return FutureBuilder<Map<String, dynamic>>(
future: _service.getProfile(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final profile = snapshot.data!;
return Column(
children: [
Text(profile['basic_info']['full_name']),
Text('Age: ${profile['basic_info']['age']}'),
Text('Location: ${profile['basic_info']['location']}'),
LinearProgressIndicator(
value: profile['meta']['profile_completion'] / 100,
),
],
);
}
return CircularProgressIndicator();
},
);
}
}
class APIClient {
async makeRequest(url, options = {}) {
let response = await fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${this.token}`
}
});
// Token expired
if (response.status === 401) {
await this.refreshToken();
// Retry request with new token
response = await fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${this.token}`
}
});
}
return response;
}
async refreshToken() {
const response = await fetch('/api/mobile/auth/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.token}`
},
body: JSON.stringify({
refresh_token: this.refreshToken
})
});
const data = await response.json();
this.token = data.data.access_token;
this.refreshToken = data.data.refresh_token;
}
}
// Polling approach (simple)
class MessagingService {
startPolling(userId) {
setInterval(async () => {
const messages = await this.getNewMessages(userId);
if (messages.length > 0) {
this.handleNewMessages(messages);
}
}, 5000); // Poll every 5 seconds
}
async getNewMessages(userId) {
const response = await fetch(`/api/user/messages/${userId}?after=${this.lastMessageTime}`);
const data = await response.json();
return data.data.messages;
}
}
async function uploadProfilePhoto(file) {
const formData = new FormData();
formData.append('photo', file);
formData.append('type', 'selfie');
formData.append('is_primary', 'true');
const response = await fetch('/api/user/photos/upload', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`
},
body: formData
});
return response.json();
}
Problem: "Access to fetch at ... has been blocked by CORS policy"
Solution:
Problem: Getting 429 Too Many Requests
Solution:
// Implement exponential backoff
async function fetchWithRetry(url, options, retries = 3) {
for (let i = 0; i < retries; i++) {
const response = await fetch(url, options);
if (response.status !== 429) {
return response;
}
const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
}
throw new Error('Rate limit exceeded');
}
Problem: Where to store tokens securely?
Solution:
// Jest example
describe('ProfileAPI', () => {
it('should fetch user profile', async () => {
const mockProfile = {
basic_info: { full_name: 'Test User' }
};
fetch.mockResponseOnce(JSON.stringify({
success: true,
data: mockProfile
}));
const profile = await profileAPI.getProfile();
expect(profile.basic_info.full_name).toBe('Test User');
});
});
Use our Postman collection to create automated test suites:
nl-dating-apiNow that you're set up, try building:
Happy coding! 🚀