API v1

Developer API

Build mobile apps and integrations with our RESTful API. Authenticate with Sanctum tokens, filter with query parameters, and get responses in JSON.

Base URL

https://ghanemtech.com/api/v1

Authentication

Bearer token via Laravel Sanctum

Localization

Accept-Language: ar or ?lang=ar

Authentication Header

For protected endpoints, include the bearer token from login/register response:

Authorization: Bearer {your-token}
Accept: application/json
Accept-Language: en

Create a new user account and receive an API token.

Request Body

name string *
User's full name
email string *
Unique email address
password string *
Min 8 characters
password_confirmation string *
Must match password
device_name string *
Device identifier (e.g. "iPhone 15")

Response

{
  "user": {
    "id": 1,
    "name": "John Doe",
    "email": "[email protected]",
    "type": null,
    "profile_photo_url": "...",
    "email_verified_at": null,
    "two_factor_enabled": false,
    "created_at": "2026-02-17T..."
  },
  "token": "1|abc123..."
}

Authenticate and receive an API token.

Request Body

email string *
Registered email
password string *
Account password
device_name string *
Device identifier

Response

{
  "user": { "id": 1, "name": "John Doe", "email": "[email protected]", "type": "client" },
  "token": "2|xyz789..."
}

Revoke the current API token.

Response

{ "message": "Logged out successfully." }

Get the authenticated user's profile.

Response

{
  "data": {
    "id": 1,
    "name": "John Doe",
    "email": "[email protected]",
    "type": "client",
    "profile_photo_url": "...",
    "email_verified_at": "2026-01-01T...",
    "two_factor_enabled": false,
    "created_at": "2026-01-01T..."
  }
}

Update the authenticated user's name or email.

Request Body

name string
New display name
email string
New email address

Response

{
  "user": { "id": 1, "name": "Updated Name", "email": "[email protected]" },
  "message": "Profile updated successfully."
}

Change the authenticated user's password.

Request Body

current_password string *
Current password
password string *
New password (min 8)
password_confirmation string *
Confirm new password

Response

{ "message": "Password changed successfully." }

Send a password reset link to the given email.

Request Body

email string *
Registered email address

Response

{ "message": "We have emailed your password reset link." }

Reset password using the token from the email link.

Request Body

token string *
Reset token from email
email string *
Email address
password string *
New password
password_confirmation string *
Confirm password

Response

{ "message": "Your password has been reset." }

Get all home page data: services, featured projects, clients, latest blogs, stats, and testimonials.

Response

{
  "services": [{ "id": 1, "title": "Web Development", "slug": "web-development", ... }],
  "projects": [{ "id": 1, "name": "Project X", "slug": "project-x", "logo_url": "...", ... }],
  "clients": [{ "id": 1, "name": "Acme Corp", "logo_url": "..." }],
  "blogs": [{ "id": 1, "title": "Latest Post", "slug": "latest-post", ... }],
  "stats": { "projects": 25, "clients": 15, "team_members": 10, "lines_of_code": "500K+" },
  "testimonials": [{ "name": "...", "role": "...", "content": "..." }]
}

Get team members, company vision and mission.

Response

{
  "team_members": [{ "id": 1, "name": "...", "role": "...", "bio": "...", "photo_url": "..." }],
  "vision": "Our vision statement...",
  "mission": "Our mission statement..."
}

List all active services, ordered by sort position.

Response

{
  "data": [
    { "id": 1, "title": "Web Development", "description": "...", "slug": "web-development", "icon_url": "..." }
  ]
}

Get a single service with up to 3 related projects.

Response

{
  "data": {
    "id": 1, "title": "Web Development", "description": "...", "slug": "web-development",
    "icon_url": "...",
    "projects": [{ "id": 1, "name": "Project X", "slug": "project-x" }]
  }
}

List all active projects. Supports filtering by service and sorting.

Query Parameters

filter[service] string
Filter by service slug (e.g. web-development)
sort string
Sort by sort or created_at (prefix with - for desc)

Response

{
  "data": [
    {
      "id": 1, "name": "Project X", "slug": "project-x", "url": "https://...",
      "logo_url": "...", "gallery": [{ "id": 1, "url": "...", "name": "..." }],
      "services": [{ "id": 1, "title": "Web Development" }]
    }
  ]
}

Get a single project with its services and media gallery.

Response

{
  "data": {
    "id": 1, "name": "Project X", "description": "...", "slug": "project-x",
    "url": "https://...", "logo_url": "...", "logo_thumb_url": "...",
    "gallery": [{ "id": 1, "url": "...", "file_name": "screenshot.png" }],
    "services": [{ "id": 1, "title": "Web Development" }]
  }
}

List all visible blog posts with pagination. Supports sorting.

Query Parameters

sort string
Sort by created_at, title_en, title_ar, updated_at
page integer
Page number (15 per page)

Response

{
  "data": [{ "id": 1, "title": "...", "slug": "...", "small_description": "...", "thumb_url": "..." }],
  "links": { "first": "...", "last": "...", "prev": null, "next": "..." },
  "meta": { "current_page": 1, "last_page": 3, "per_page": 15, "total": 42 }
}

Get a single blog post with 3 recent related posts.

Response

{
  "blog": { "id": 1, "title": "...", "body": "...", "slug": "...", "image_url": "..." },
  "recent_posts": [{ "id": 2, "title": "...", "slug": "...", "thumb_url": "..." }]
}

List all active FAQs, ordered by sort position.

Response

{
  "data": [{ "id": 1, "question": "How do I get started?", "answer": "...", "sort_order": 1 }]
}

List all active process steps, ordered by sort position.

Response

{
  "data": [{ "id": 1, "title": "Discovery", "description": "...", "sort_order": 1, "image_url": "..." }]
}

Submit a contact form message. Rate limited to 5 requests per minute.

Request Body

name string *
Your full name
email string *
Your email address
message string *
Your message

Response

{ "message": "Contact message submitted successfully." }

Get the authenticated client's dashboard with their projects.

Response

{
  "user": { "id": 1, "name": "John Doe", "email": "[email protected]", "type": "client" },
  "client_projects": [
    {
      "id": 1, "name": "My App", "status": "active", "progress": 65,
      "start_date": "2026-01-01", "due_date": "2026-06-01"
    }
  ]
}

Get detailed project info including paid payments with invoices, services, and proposals. Only accessible by the project's owner.

Response

{
  "data": {
    "id": 1, "name": "My App", "description": "...", "status": "active",
    "progress": 65, "start_date": "2026-01-01", "due_date": "2026-06-01",
    "links": [{ "title": "GitHub", "url": "https://..." }],
    "services": [{ "id": 1, "title": "Mobile Development" }],
    "payments": [{
      "id": 1, "amount": "5000.00", "currency": "EGP", "status": "paid",
      "invoice": { "uuid": "abc-123", "invoice_number": "INV-001", "pdf_url": "..." }
    }],
    "proposals": [{ "uuid": "def-456", "title": "Phase 1", "status": "accepted" }]
  }
}

Submit a new project request. A client record will be auto-created if one doesn't exist for the user.

Request Body

name string *
Project name
description string *
Project description
services array *
Array of service IDs

Response

{
  "message": "Project request submitted successfully.",
  "project": { "id": 5, "name": "New Project", "status": "pending" }
}

All document endpoints return PDF binary data with Content-Type: application/pdf. The /pdf variants stream inline, while /download variants trigger a file download. Only accessible by the client who owns the related project.

Stream an invoice PDF inline in the browser.

Download an invoice as a PDF file.

Stream a proposal PDF inline.

Download a proposal as a PDF file.

Stream a contract PDF inline.

Download a contract as a PDF file.

Error Responses

Code Meaning Example
401 Unauthenticated {"message": "Unauthenticated."}
403 Forbidden {"message": "Unauthorized access to this project."}
404 Not Found {"message": "No query results for model..."}
422 Validation Error {"message": "...", "errors": {"email": ["..."]}}
429 Too Many Requests {"message": "Too Many Attempts."}