Back to Dashboard

API Documentation

NL-Dating API Documentation

Table of Contents

  1. Introduction
  2. Getting Started
  3. Authentication
  4. Rate Limiting
  5. Error Handling
  6. API Endpoints
  7. Integration Guide
  8. Best Practices
  9. Changelog

Introduction

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.

Base URL

Production: https://api.nl-dating.com
Development: http://localhost:8000/api

API Version

Current Version: v1 (2.17.0)

Response Format

All responses are returned in JSON format with consistent structure:

{
  "success": true,
  "message": "Operation completed successfully",
  "data": {
    // Response data here
  }
}

Getting Started

Prerequisites

  • Registered account on NL-Dating platform
  • API credentials (obtained after registration)
  • HTTPS-enabled endpoint for webhooks (optional)

Quick Start

  1. Register a user account
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"
  }'
  1. Obtain authentication token
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"
  }'
  1. Make your first API call
curl -X GET https://api.nl-dating.com/api/user/profile \
  -H "Authorization: Bearer YOUR_TOKEN_HERE"

Authentication

Overview

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.

Token Types

Access Token

  • Purpose: Authenticate API requests
  • Lifetime: 7 days (10,080 minutes)
  • Format: Bearer token
  • Usage: Include in Authorization header

Refresh Token

  • Purpose: Obtain new access tokens
  • Lifetime: 30 days
  • Format: Opaque string
  • Usage: Send to refresh endpoint

Authentication Flow

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

Token Management

Creating Tokens

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": ["*"]
  }
}

Refreshing Tokens

POST /api/mobile/auth/refresh
Content-Type: application/json
Authorization: Bearer YOUR_CURRENT_TOKEN

{
  "refresh_token": "xyz789..."
}

Revoking Tokens

POST /api/mobile/auth/logout
Authorization: Bearer YOUR_TOKEN

Token Abilities (Scopes)

Tokens can have specific abilities that limit their access:

  • profile:read - Read user profile
  • profile:write - Update user profile
  • matches:read - View matches
  • meetings:manage - Create/update meetings
  • messages:send - Send messages
  • payments:create - Create payments
  • premium:access - Access premium features
  • * - Full access (default)

Rate Limiting

Overview

API rate limits prevent abuse and ensure fair usage. Limits vary by endpoint and user type.

Rate Limit Headers

All responses include rate limit information:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1623456789

Rate Limits by Endpoint

| 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 |

Handling Rate Limits

When rate limit is exceeded:

{
  "success": false,
  "message": "Too many requests. Please try again later.",
  "error_code": "RATE_LIMIT_EXCEEDED",
  "retry_after": 60
}

Error Handling

HTTP Status Codes

| 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 |

Error Response Format

{
  "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."]
  }
}

Common Error Codes

  • AUTHENTICATION_FAILED - Invalid credentials
  • TOKEN_EXPIRED - Access token expired
  • VALIDATION_ERROR - Input validation failed
  • RESOURCE_NOT_FOUND - Requested resource doesn't exist
  • INSUFFICIENT_PERMISSIONS - Lacking required permissions
  • RATE_LIMIT_EXCEEDED - Too many requests
  • PAYMENT_REQUIRED - Premium feature requires payment
  • MAINTENANCE_MODE - API under maintenance

API Endpoints

Authentication Endpoints

Register User

POST /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..."
  }
}

Login

POST /api/mobile/auth/login

Logout

POST /api/mobile/auth/logout
Authorization: Bearer YOUR_TOKEN

Refresh Token

POST /api/mobile/auth/refresh

User Profile Endpoints

Get Profile

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
    }
  }
}

Update Profile

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 Profile Completion

GET /api/user/profile/completion

Get Profile Quality

GET /api/user/profile/quality

Update Preferences

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"
}

Update Privacy Settings

PUT /api/user/profile/privacy

Get Validation Rules

GET /api/user/profile/validation-rules

Matching Endpoints

Get Recent Matches

GET /api/user/matches/recent

Query Parameters:

  • page (integer): Page number
  • per_page (integer): Items per page (max 50)
  • status (string): Filter by status

Response:

{
  "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 Match Details

GET /api/user/matches/{matchId}

Get Match Statistics

GET /api/user/matches/statistics

Meetings Endpoints

List Meetings

GET /api/user/meetings

Get Upcoming Meetings

GET /api/user/meetings/upcoming

Get Meeting Details

GET /api/user/meetings/{meetingId}

Reschedule Meeting

PUT /api/user/meetings/{meetingId}/reschedule

Request Body:

{
  "new_date": "2025-06-15",
  "new_time": "19:00",
  "reason": "Work commitment"
}

Cancel Meeting

DELETE /api/user/meetings/{meetingId}/cancel

Messaging Endpoints

Get Conversations

GET /api/user/conversations

Get Messages

GET /api/user/messages/{userId}

Query Parameters:

  • before (timestamp): Get messages before this time
  • limit (integer): Number of messages (max 100)

Send Message

POST /api/user/messages/send

Request Body:

{
  "recipient_id": 789,
  "message": "Hello! How are you?",
  "type": "text"
}

Delete Message

DELETE /api/user/messages/{messageId}

Mark Messages as Read

POST /api/user/messages/mark-read

Payment Endpoints

Get Payment History

GET /api/user/payments

Create Payment

POST /api/user/payments

Request Body (multipart/form-data):

  • meeting_id (required): Meeting ID
  • bank_name (required): Bank name
  • account_holder (required): Account holder name
  • account_number (required): Account number
  • amount (required): Payment amount
  • payment_proof (required): Proof file (image/pdf)

Get Payment Info

GET /api/user/payments/info

Safety Endpoints

Get Blocked Users

GET /api/user/safety/blocked

Block User

POST /api/user/safety/block

Request Body:

{
  "user_id": 999,
  "reason": "harassment",
  "details": "Inappropriate messages"
}

Unblock User

DELETE /api/user/safety/unblock/{userId}

Report User

POST /api/user/safety/report

Request Body:

{
  "reported_user_id": 999,
  "category": "fake_profile",
  "description": "Using stolen photos",
  "evidence_urls": ["https://..."],
  "urgency": "high"
}

Get Safety Guidelines

GET /api/user/safety/guidelines

Discovery Endpoints

Discover Users

GET /api/discovery/discover

Query Parameters:

  • latitude (float): User latitude
  • longitude (float): User longitude
  • radius (integer): Search radius in km

Search Users

GET /api/discovery/search

Query Parameters:

  • q (string): Search query
  • filters (object): Filter criteria

Like User

POST /api/discovery/like

Request Body:

{
  "user_id": 999,
  "super_like": false
}

Pass User

POST /api/discovery/pass

Notification Endpoints

Get Notification Counts

GET /api/user/notifications/counts

Get Recent Notifications

GET /api/user/notifications/recent

Mark Notifications as Read

POST /api/user/notifications/mark-read

Request Body:

{
  "notification_ids": [1, 2, 3]
}

Integration Guide

Mobile App Integration

iOS (Swift)

// 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)
    }
}

Android (Kotlin)

// 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)
        }
    }
}

Web App Integration

React

// 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>
  );
}

Vue.js

// 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>

Webhook Integration

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"
  ]
}

Webhook Event Format

{
  "event": "match.created",
  "timestamp": "2025-06-07T10:30:00Z",
  "data": {
    "match_id": 123,
    "user_id": 456,
    "matched_user_id": 789,
    "compatibility_score": 85
  }
}

Best Practices

1. Authentication

  • Store tokens securely (Keychain on iOS, Keystore on Android)
  • Implement token refresh logic before expiration
  • Clear tokens on logout
  • Use device-specific names for token management

2. Error Handling

  • Implement retry logic for network failures
  • Handle rate limit errors gracefully
  • Show user-friendly error messages
  • Log errors for debugging

3. Performance

  • Cache frequently accessed data
  • Implement pagination for large datasets
  • Use conditional requests with ETags
  • Compress request payloads

4. Security

  • Always use HTTPS
  • Validate SSL certificates
  • Sanitize user input
  • Never store sensitive data in plain text

5. User Experience

  • Show loading indicators
  • Implement optimistic updates
  • Handle offline scenarios
  • Provide feedback for all actions

Changelog

Version 2.17.0 (2025-06-07)

  • Added comprehensive security measures
  • Implemented token abilities/scopes
  • Enhanced rate limiting with premium multipliers
  • Added refresh token support

Version 2.16.0 (2025-06-07)

  • Added payment endpoints
  • Added feedback endpoints
  • Added contact sharing endpoints
  • Added safety endpoints
  • Added venue endpoints

Version 2.15.0 (2025-06-07)

  • Removed public frontend components
  • Transitioned to backend-only API architecture

Version 2.14.0 (2025-06-07)

  • Extended profile system with 32+ fields
  • Added profile quality assessment
  • Enhanced matching algorithm

Support

Contact

  • Email: api-support@nl-dating.com
  • Developer Portal: https://developers.nl-dating.com
  • Status Page: https://status.nl-dating.com

Resources

Rate Limit Support

If you need higher rate limits for your application, contact our support team with:

  • Your application details
  • Expected request volume
  • Use case description

© 2025 NL-Dating. All rights reserved.