API Documentation
Integrate HaoChi into your applications. Authentication, profile management and more.
Overview
Base URL
https://haochi.it/api
Required headers
All requests must include the following headers:
Content-Type: application/json
Accept: application/json
Response format
All responses are in JSON format with the following structure:
Example response 200
{
"success": true,
"message": "...",
"data": { ... }
}
Example response 201
{
"success": true,
"message": "...",
"data": { ... }
}
Authentication
User endpoints require a Bearer token in the Authorization header:
Authorization: Bearer <token>
API Key
Product endpoints require a static API key in the X-Api-Key header:
X-Api-Key: <api_key>
Rate Limiting
Authentication endpoints are limited to 5 requests per minute per IP. Product endpoints are limited to 30 requests per minute per IP.
Error responses
Error responses 401
{
"success": false,
"message": "Invalid credentials."
}
Error responses 422
{
"message": "The email field is required.",
"errors": {
"email": [
"The email field is required."
]
}
}
/api/auth/register
Register
Create a new user account with email and password.
Parameters
| Field | Type | Description | |
|---|---|---|---|
name |
string | Required | User's first name |
surname |
string | Required | User's last name |
email |
string | Required | Email address |
password |
string | Required | Password (minimum 8 characters) |
password_confirmation |
string | Required | Password confirmation |
name
User's first name
surname
User's last name
email
Email address
password
Password (minimum 8 characters)
password_confirmation
Password confirmation
Example response 201
{
"success": true,
"message": "Registration successful.",
"data": {
"user": {
"id": 1,
"name": "Marco",
"surname": "Rossi",
"full_name": "Marco Rossi",
"email": "marco@example.com",
"email_verified": false,
"avatar": null,
"google_linked": false,
"google_locale": null,
"created_at": "2025-01-15T10:30:00+00:00",
"updated_at": "2025-01-15T10:30:00+00:00"
},
"token": "1|abc123..."
}
}
/api/auth/login
Login
Authenticate an existing user with email and password.
Note: If the user registered via Google and has no password, the response will be a 401 with the message: "Invalid credentials. If you signed up with Google, please use Google Sign-In."
Parameters
| Field | Type | Description | |
|---|---|---|---|
email |
string | Required | Email address |
password |
string | Required | Password (minimum 8 characters) |
email
Email address
password
Password (minimum 8 characters)
Example response 200
{
"success": true,
"message": "Login successful.",
"data": {
"user": {
"id": 1,
"name": "Marco",
"surname": "Rossi",
"full_name": "Marco Rossi",
"email": "marco@example.com",
"email_verified": false,
"avatar": null,
"google_linked": false,
"google_locale": null,
"created_at": "2025-01-15T10:30:00+00:00",
"updated_at": "2025-01-15T10:30:00+00:00"
},
"token": "2|def456..."
}
}
/api/auth/google
Google Sign-In
Authenticate or register a user via Google ID token. If the account does not exist, it will be created automatically.
Parameters
| Field | Type | Description | |
|---|---|---|---|
id_token |
string | Required | ID token obtained from Google Sign-In |
id_token
ID token obtained from Google Sign-In
Example response 200
{
"success": true,
"message": "Login via Google successful.",
"data": {
"user": {
"id": 2,
"name": "Laura",
"surname": "Bianchi",
"full_name": "Laura Bianchi",
"email": "laura@gmail.com",
"email_verified": true,
"avatar": "https://lh3.googleusercontent.com/...",
"google_linked": true,
"google_locale": "it",
"created_at": "2025-01-15T10:30:00+00:00",
"updated_at": "2025-01-15T10:30:00+00:00"
},
"token": "3|ghi789...",
"is_new": false
}
}
/api/user
Requires authentication
User profile
Retrieve the authenticated user's profile.
Example response 200
{
"success": true,
"message": "User profile retrieved.",
"data": {
"id": 1,
"name": "Marco",
"surname": "Rossi",
"full_name": "Marco Rossi",
"email": "marco@example.com",
"email_verified": false,
"avatar": null,
"google_linked": false,
"google_locale": null,
"created_at": "2025-01-15T10:30:00+00:00",
"updated_at": "2025-01-15T10:30:00+00:00"
}
}
/api/user
Requires authentication
Update profile
Update the authenticated user's profile data. Only send the fields you want to change.
Parameters
| Field | Type | Description | |
|---|---|---|---|
name |
string | Optional | User's first name |
surname |
string | Optional | User's last name |
email |
string | Optional | Email address |
name
User's first name
surname
User's last name
email
Email address
Example response 200
{
"success": true,
"message": "Profile updated.",
"data": {
"id": 1,
"name": "Marco",
"surname": "Verdi",
"full_name": "Marco Verdi",
"email": "marco@example.com",
"email_verified": false,
"avatar": null,
"google_linked": false,
"google_locale": null,
"created_at": "2025-01-15T10:30:00+00:00",
"updated_at": "2025-01-15T11:00:00+00:00"
}
}
/api/auth/logout
Requires authentication
Logout
Revoke the current access token of the authenticated user.
Example response 200
{
"success": true,
"message": "Logged out successfully.",
"data": null
}
User resource
All endpoints that return user data use the following structure:
| Field | Type | Description |
|---|---|---|
id |
integer | Unique identifier |
name |
string | First name |
surname |
string | Last name |
full_name |
string | Full name |
email |
string | Email address |
email_verified |
boolean | Whether the email is verified |
avatar |
string | Avatar URL (from Google) |
google_linked |
boolean | Whether a Google account is linked |
google_locale |
string | Google account locale |
created_at |
string | Creation date (ISO 8601) |
updated_at |
string | Last update date (ISO 8601) |
id
integer
Unique identifier
name
string
First name
surname
string
Last name
full_name
string
Full name
email
string
Email address
email_verified
boolean
Whether the email is verified
avatar
string
Avatar URL (from Google)
google_linked
boolean
Whether a Google account is linked
google_locale
string
Google account locale
created_at
string
Creation date (ISO 8601)
updated_at
string
Last update date (ISO 8601)
Product resource
The product lookup endpoint returns the following structure:
| Field | Type | Description |
|---|---|---|
id |
integer | Unique identifier |
barcode |
string | EAN barcode |
product_name |
string | Product name |
product_name_it |
string | Product name in Italian |
brand |
string | Brand |
image_url |
string | Product image URL |
nutriscore_grade |
string | Nutri-Score grade (a-e) |
ecoscore_grade |
string | Eco-Score grade (a-e) |
nova_group |
integer | NOVA group (1-4) |
id
integer
Unique identifier
barcode
string
EAN barcode
product_name
string
Product name
product_name_it
string
Product name in Italian
brand
string
Brand
image_url
string
Product image URL
nutriscore_grade
string
Nutri-Score grade (a-e)
ecoscore_grade
string
Eco-Score grade (a-e)
nova_group
integer
NOVA group (1-4)
Nutritional values (per 100g)
| Field | Type | Description |
|---|---|---|
nutriments.energy_kcal |
decimal | Energy (kcal) |
nutriments.fat |
decimal | Fat (g) |
nutriments.saturated_fat |
decimal | Saturated fat (g) |
nutriments.carbohydrates |
decimal | Carbohydrates (g) |
nutriments.sugars |
decimal | Sugars (g) |
nutriments.fiber |
decimal | Fiber (g) |
nutriments.proteins |
decimal | Proteins (g) |
nutriments.salt |
decimal | Salt (g) |
nutriments.sodium |
decimal | Sodium (g) |
nutriments.energy_kcal
decimal
Energy (kcal)
nutriments.fat
decimal
Fat (g)
nutriments.saturated_fat
decimal
Saturated fat (g)
nutriments.carbohydrates
decimal
Carbohydrates (g)
nutriments.sugars
decimal
Sugars (g)
nutriments.fiber
decimal
Fiber (g)
nutriments.proteins
decimal
Proteins (g)
nutriments.salt
decimal
Salt (g)
nutriments.sodium
decimal
Sodium (g)
Dietary filters
| Field | Type | Description |
|---|---|---|
filters.is_vegetarian |
boolean | Suitable for vegetarians |
filters.is_vegan |
boolean | Suitable for vegans |
filters.is_palm_oil_free |
boolean | Palm oil free |
filters.is_gluten_free |
boolean | Gluten free |
filters.is_lactose_free |
boolean | Lactose free |
filters.is_low_carbon |
boolean | Low environmental impact |
filters.is_diabetic_friendly |
boolean | Suitable for diabetics |
filters.is_ketogenic |
boolean | Suitable for ketogenic diet |
filters.is_vegetarian
boolean
Suitable for vegetarians
filters.is_vegan
boolean
Suitable for vegans
filters.is_palm_oil_free
boolean
Palm oil free
filters.is_gluten_free
boolean
Gluten free
filters.is_lactose_free
boolean
Lactose free
filters.is_low_carbon
boolean
Low environmental impact
filters.is_diabetic_friendly
boolean
Suitable for diabetics
filters.is_ketogenic
boolean
Suitable for ketogenic diet
/api/products/{barcode}
Requires API Key
Product lookup
Look up a food product by barcode (EAN). The product is fetched from OpenFoodFacts and cached locally for 7 days.
Note: The response includes a "source" field indicating the data origin: "cache" if served from local database, "openfoodfacts" if freshly fetched from the OpenFoodFacts API.
Parameters
| Field | Type | Description | |
|---|---|---|---|
barcode |
string | Required | EAN barcode of the product (13 digits) |
barcode
EAN barcode of the product (13 digits)
Example response 200
{
"success": true,
"message": "Product retrieved.",
"source": "cache",
"data": {
"id": 1,
"barcode": "3017620422003",
"product_name": "Nutella",
"product_name_it": "Nutella",
"brand": "Ferrero",
"image_url": "https://images.openfoodfacts.net/...",
"nutriscore_grade": "e",
"ecoscore_grade": null,
"nova_group": 4,
"nutriments": {
"energy_kcal": "539.000",
"fat": "30.900",
"saturated_fat": "10.600",
"carbohydrates": "57.500",
"sugars": "56.300",
"fiber": "0.000",
"proteins": "6.300",
"salt": "0.107",
"sodium": "0.043"
},
"filters": {
"is_vegetarian": true,
"is_vegan": false,
"is_palm_oil_free": false,
"is_gluten_free": true,
"is_lactose_free": false,
"is_low_carbon": false,
"is_diabetic_friendly": false,
"is_ketogenic": false
},
"last_fetched_at": "2026-02-17T10:55:47+00:00",
"created_at": "2026-02-17T10:55:47+00:00",
"updated_at": "2026-02-17T10:55:47+00:00"
}
}
Error responses 404
{
"success": false,
"message": "Product not found."
}
HTTP Status Codes
The API uses the following HTTP status codes:
| Status | Description |
|---|---|
| 200 | Request completed successfully |
| 201 | Resource created successfully |
| 401 | Not authenticated or invalid credentials |
| 403 | Access denied |
| 404 | Resource not found |
| 422 | Validation error in submitted data |
| 429 | Too many requests (rate limit exceeded) |
| 500 | Internal server error |