API Documentation

Complete reference for the RecipeBook API

Introduction

Welcome to the RecipeBook API! Our REST API provides a simple, yet powerful interface to access and manage recipes, categories, tags, and more.

The API is built with Laravel and follows REST conventions. All responses are in JSON format.

Base URL: https://recipe.rmartorell.nl/api/v1

Authentication

Currently, the RecipeBook API does not require authentication. All endpoints are publicly accessible.

Note: Authentication may be added in future versions for write operations.

Response Format

All API responses follow a consistent JSON format:

{
  "data": [
    { /* resource object */ }
  ],
  "links": {
    "first": "...",
    "last": "..."
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "per_page": 15,
    "to": 15,
    "total": 15
  }
}

Filtering

The API supports filtering using query parameters. Use the following format to filter results:

GET https://recipe.rmartorell.nl/api/v1/endpoint?filter[field][operator]=value

Supported Operators:

Operator Description Example
eq Equal to ?filter[id][eq]=1
like Contains (case-insensitive) ?filter[name][like]=pizza
lt Less than ?filter[id][lt]=10
gt Greater than ?filter[id][gt]=1

Endpoints

Recipes

Manage and retrieve recipes

List Recipes

GET
GET https://recipe.rmartorell.nl/api/v1/recipes

Retrieve a paginated list of all recipes with their categories, tags, and descriptions.

Query Parameters
  • filter[name][like] - Filter by recipe name
Example Response
https://recipe.rmartorell.nl/api/v1/recipes?filter[name][like]=pasta

Get Single Recipe

GET
GET https://recipe.rmartorell.nl/api/v1/recipes/{id}

Retrieve a single recipe by its ID with all associated data.

Path Parameters
  • id - Recipe ID (integer)
Example
https://recipe.rmartorell.nl/api/v1/recipes/1

Categories

Manage recipe categories

List Categories

GET
GET https://recipe.rmartorell.nl/api/v1/categories

Retrieve a paginated list of all categories with recipe counts.

Query Parameters
  • filter[name][like] - Filter by category name
Example
https://recipe.rmartorell.nl/api/v1/categories?filter[name][like]=dessert

Get Single Category

GET
GET https://recipe.rmartorell.nl/api/v1/categories/{id}

Retrieve a single category by its ID with recipe count.

Path Parameters
  • id - Category ID (integer)
Example
https://recipe.rmartorell.nl/api/v1/categories/1

Tags

Manage recipe tags

List Tags

GET
GET https://recipe.rmartorell.nl/api/v1/tags

Retrieve a paginated list of all tags with recipe counts.

Query Parameters
  • filter[name][like] - Filter by tag name
Example
https://recipe.rmartorell.nl/api/v1/tags?filter[name][like]=vegetarian

Get Single Tag

GET
GET https://recipe.rmartorell.nl/api/v1/tags/{id}

Retrieve a single tag by its ID with recipe count.

Path Parameters
  • id - Tag ID (integer)
Example
https://recipe.rmartorell.nl/api/v1/tags/1

Response Objects

Recipe Object

{
  "id": 1,
  "name": "Spaghetti Carbonara",
  "category": {
    "id": 1,
    "name": "Italian",
    "recipes_count": 12
  },
  "tags": [
    {
      "id": 1,
      "name": "Quick",
      "recipes_count": 45
    }
  ],
  "descriptions": [
    {
      "id": 1,
      "description": "Traditional Italian pasta...",
      "language": {
        "id": 1,
        "code": "en",
        "name": "English"
      }
    }
  ]
}

Category Object

{
  "id": 1,
  "name": "Italian",
  "recipes_count": 12
}

Tag Object

{
  "id": 1,
  "name": "Quick",
  "recipes_count": 45
}

Filter Examples

Filter Recipes by Name (Partial Match)

Search for recipes containing a specific word or phrase using the like operator for case-insensitive matching.

Request URL:
GET https://recipe.rmartorell.nl/api/v1/recipes?filter[name][like]=pasta

Returns all recipes with names containing "pasta" (case-insensitive)

Response Example:
{
  "data": [
    {
      "id": 1,
      "name": "Spaghetti Carbonara",
      "category": {
        "id": 2,
        "name": "Italian",
        "recipes_count": 12
      },
      "tags": [
        {
          "id": 1,
          "name": "Quick",
          "recipes_count": 45
        }
      ],
      "descriptions": [
        {
          "id": 1,
          "description": "<p>Traditional Italian pasta...</p>",
          "language": {
            "id": 1,
            "code": "en",
            "name": "English"
          }
        }
      ],
      "ingredients": {
        "en": {
          "language": {
            "code": "en",
            "name": "English",
            "id": 1
          },
          "items": [
            {
              "id": 1,
              "name": "Spaghetti",
              "quantity": "400",
              "unit": "gram",
              "order": 0
            },
            {
              "id": 2,
              "name": "Eggs",
              "quantity": "4",
              "unit": "pieces",
              "order": 1
            }
          ]
        },
        "nl": {
          "language": {
            "code": "nl",
            "name": "Dutch",
            "id": 2
          },
          "items": [
            {
              "id": 1,
              "name": "Spaghetti",
              "quantity": "400",
              "unit": "gram",
              "order": 0
            },
            {
              "id": 2,
              "name": "Eieren",
              "quantity": "4",
              "unit": "stuks",
              "order": 1
            }
          ]
        },
        "original": [
          {
            "id": 1,
            "name": "Spaghetti",
            "quantity": "400",
            "unit": "gram",
            "order": 0
          },
          {
            "id": 2,
            "name": "Eggs",
            "quantity": "4",
            "unit": "pieces",
            "order": 1
          }
        ]
      }
    }
  ]
}

Tip: The like operator searches anywhere within the field. For example:

  • ?filter[name][like]=pasta matches "Spaghetti Carbonara", "Pasta Primavera", "Fresh Pasta"
  • ?filter[name][like]=cake matches "Chocolate Cake", "Cheesecake", "Birthday Cake"

Filter Recipes by Exact Name

Search for recipes with an exact name match using the eq operator (case-sensitive).

Request URL:
GET https://recipe.rmartorell.nl/api/v1/recipes?filter[name][eq]=Spaghetti Carbonara

Returns only recipes with the exact name "Spaghetti Carbonara"

Response Example:
{
  "data": [
    {
      "id": 1,
      "name": "Spaghetti Carbonara",
      "category": {
        "id": 2,
        "name": "Italian",
        "recipes_count": 12
      },
      "tags": [
        {
          "id": 1,
          "name": "Quick",
          "recipes_count": 45
        }
      ],
      "descriptions": [
        {
          "id": 1,
          "description": "<p>Traditional Italian pasta...</p>",
          "language": {
            "id": 1,
            "code": "en",
            "name": "English"
          }
        }
      ],
      "ingredients": {
        "en": {
          "language": {
            "code": "en",
            "name": "English",
            "id": 1
          },
          "items": [
            {
              "id": 1,
              "name": "Spaghetti",
              "quantity": "400",
              "unit": "gram",
              "order": 0
            }
          ]
        },
        "original": [
          {
            "id": 1,
            "name": "Spaghetti",
            "quantity": "400",
            "unit": "gram",
            "order": 0
          }
        ]
      }
    }
  ]
}

Note: The eq operator requires an exact match and is case-sensitive. For partial matches or case-insensitive searches, use like instead.

Combining Multiple Filters

You can combine multiple filters to narrow down results. Currently, the API supports filtering by name.

Request URL:
GET https://recipe.rmartorell.nl/api/v1/recipes?filter[name][like]=pizza&filter[id][gt]=5

Returns recipes with names containing "pizza" AND id greater than 5

Available Filter Combinations:
Operator SQL Equivalent Use Case
eq = Exact match
like LIKE Partial/substring match (case-insensitive)
lt < Less than (for numeric fields)
gt > Greater than (for numeric fields)

Ingredients Structure

Recipe ingredients are returned grouped by language for easy multilingual support. Each recipe includes ingredients in all available translated languages, plus the original ingredients.

Structure Format

The ingredients field is an object with language codes as keys:

"ingredients": {
  "en": {
    "language": {
      "code": "en",
      "name": "English",
      "id": 1
    },
    "items": [
      {
        "id": 1,
        "name": "Flour",
        "quantity": "200",
        "unit": "gram",
        "order": 0
      }
    ]
  },
  "nl": {
    "language": {
      "code": "nl",
      "name": "Dutch",
      "id": 2
    },
    "items": [
      {
        "id": 1,
        "name": "Bloem",
        "quantity": "200",
        "unit": "gram",
        "order": 0
      }
    ]
  },
  "original": [
    {
      "id": 1,
      "name": "Flour",
      "quantity": "200",
      "unit": "gram",
      "order": 0
    }
  ]
}

Key Components

Language Keys (e.g., "en", "nl", "az")

Each language code contains translated ingredients for that language, sorted alphabetically by language code.

"original"

Contains the base ingredients in the recipe's default language. Always appears last.

language

Metadata about the language (code, name, id) for each language group.

items

Array of translated ingredients, each with id, name, quantity, unit, and order.

Usage Examples

JavaScript - Get Specific Language

// Get Dutch ingredients
const dutchIngredients = recipe.ingredients.nl?.items || [];

// Get English ingredients
const englishIngredients = recipe.ingredients.en?.items || [];

// Fallback to original if translation doesn't exist
const ingredients = recipe.ingredients.nl?.items || recipe.ingredients.original;

JavaScript - Loop All Languages

// Get all available language codes
const languages = Object.keys(recipe.ingredients).filter(k => k !== 'original');

// Loop through each language
languages.forEach(langCode => {
  const group = recipe.ingredients[langCode];
  console.log(`${group.language.name}:`);
  group.items.forEach(ing => {
    console.log(`- ${ing.quantity} ${ing.unit} ${ing.name}`);
  });
});

Code Examples

JavaScript / Fetch API

// Get all recipes
fetch('https://recipe.rmartorell.nl/api/v1/recipes')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

// Search for recipes by name (partial match, case-insensitive)
fetch('https://recipe.rmartorell.nl/api/v1/recipes?filter[name][like]=pasta')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

// Search for exact recipe name
fetch('https://recipe.rmartorell.nl/api/v1/recipes?filter[name][eq]=Spaghetti Carbonara')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

// Get a specific recipe by ID
fetch('https://recipe.rmartorell.nl/api/v1/recipes/1')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

PHP / Laravel (HTTP Client)

use Illuminate\Support\Facades\Http;

// Get all recipes
$response = Http::get('https://recipe.rmartorell.nl/api/v1/recipes');
$recipes = $response->json();

// Search for recipes by name (partial match, case-insensitive)
$response = Http::get('https://recipe.rmartorell.nl/api/v1/recipes', [
    'filter' => ['name' => ['like' => 'pasta']]
]);
$recipes = $response->json();

// Search for exact recipe name
$response = Http::get('https://recipe.rmartorell.nl/api/v1/recipes', [
    'filter' => ['name' => ['eq' => 'Spaghetti Carbonara']]
]);
$recipes = $response->json();

// Get a specific recipe by ID
$response = Http::get('https://recipe.rmartorell.nl/api/v1/recipes/1');
$recipe = $response->json();

cURL

# Get all recipes
curl "https://recipe.rmartorell.nl/api/v1/recipes"

# Search for recipes by name (partial match, case-insensitive)
curl "https://recipe.rmartorell.nl/api/v1/recipes?filter[name][like]=pasta"

# Search for exact recipe name
curl "https://recipe.rmartorell.nl/api/v1/recipes?filter[name][eq]=Spaghetti Carbonara"

# Get a specific recipe by ID
curl "https://recipe.rmartorell.nl/api/v1/recipes/1"

Error Handling

The API returns standard HTTP status codes to indicate the result of an API request. In case of errors, a JSON response will be provided with error details and the appropriate HTTP status code.

400 Bad Request / 422 Unprocessable Entity

Invalid filter operators or malformed filter parameters

{
  "error": "Validation Failed",
  "message": "The provided data failed validation.",
  "errors": {
    "filter.name.invalidop": [
      "Invalid operator 'invalidop' for field 'name'. Allowed operators: like, eq"
    ]
  },
  "status": 422
}

Test URLs:

https://recipe.rmartorell.nl/api/v1/recipes?filter[name][invalidop]=test https://recipe.rmartorell.nl/api/v1/recipes?filter[id][badop]=5

404 Not Found - Resource

The requested resource does not exist

{
  "error": "Not Found",
  "message": "The requested resource was not found.",
  "status": 404
}

Test URLs:

https://recipe.rmartorell.nl/api/v1/recipes/99999 https://recipe.rmartorell.nl/api/v1/categories/99999 https://recipe.rmartorell.nl/api/v1/tags/99999

404 Not Found - Endpoint

The requested API endpoint does not exist

{
  "error": "Route Not Found",
  "message": "The requested API endpoint does not exist. Please check the API documentation at /api-docs",
  "status": 404
}

Test URLs:

https://recipe.rmartorell.nl/api/v1/invalid https://recipe.rmartorell.nl/api/v1/recipes/invalid/endpoint https://recipe.rmartorell.nl/api/v1/nonexistent

422 Unprocessable Entity

The request was well-formed but contains validation errors

{
  "error": "Validation Failed",
  "message": "The provided data failed validation.",
  "errors": {
    "name": [
      "The name field is required."
    ]
  },
  "status": 422
}

Note:

This error occurs during POST/PUT requests with invalid data validation (read-only API currently)

500 Internal Server Error

An unexpected server error occurred

{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred. Please try again later.",
  "status": 500
}

Note:

This error occurs when the server encounters an unexpected condition. Contact support if you encounter this error.

HTTP Status Codes Reference

Code Meaning Description
200 OK Request succeeded
400 Bad Request Invalid parameters or request format
404 Not Found Resource or endpoint not found
422 Unprocessable Entity Validation errors in request data
500 Internal Server Error Server-side error occurred

Need Help?

If you have any questions or need assistance with the API, feel free to reach out to our support team.

Back to Home