API Documentation

The Fellowship of the Fork API provides a RESTful JSON interface for building integrations with our cannabis edibles recipe platform. Use it to manage recipes, strains, collections, and more.

Base URL

https://fellowshipofthefork.com/api/v1

Request Format

All request bodies should be sent as JSON with the Content-Type: application/json header.

Authentication

Most endpoints require a Bearer token. Obtain one via the login or signup endpoint, then include it in all requests:

Authorization: Bearer YOUR_API_TOKEN

Pagination

List endpoints return paginated results. Use the per_page parameter to control page size. Pagination metadata is included in the meta key of the response.

{
  "meta": {
    "current_page": 1,
    "total_pages": 5,
    "total_count": 48,
    "per_page": 10
  }
}

Authentication

Create accounts, log in, and manage sessions. Tokens are 64-character hex strings returned on signup and login.

POST /api/v1/auth/signup

Create a new user account and receive an API token.

Parameters

NameTypeRequiredDescription
usernamestringYesUnique username
emailstringNoEmail address
passwordstringYesPassword (min 6 characters)
password_confirmationstringYesMust match password
age_verifiedbooleanYesMust be true (21+ confirmation)
terms_acceptedbooleanYesMust be true

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/auth/signup \
  -H "Content-Type: application/json" \
  -d '{
    "username": "samwise",
    "email": "[email protected]",
    "password": "p0tat03s",
    "password_confirmation": "p0tat03s",
    "age_verified": true,
    "terms_accepted": true
  }'

Example Response

{
  "user": {
    "id": 1,
    "username": "samwise",
    "email": "[email protected]",
    "display_name": null,
    "bio": null,
    "points": 0,
    "admin": false,
    "badges_count": 0,
    "recipes_count": 0,
    "strains_count": 0,
    "preferences": {
      "profile_visible": true,
      "show_recipes": true,
      "show_strains": true
    },
    "created_at": "2026-01-15T10:30:00Z"
  },
  "token": "a1b2c3d4e5f6..."
}
POST /api/v1/auth/login

Authenticate with username and password to receive an API token.

Parameters

NameTypeRequiredDescription
usernamestringYesYour username
passwordstringYesYour password

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username": "samwise", "password": "p0tat03s"}'

Example Response

{
  "user": {
    "id": 1,
    "username": "samwise",
    "points": 150,
    "badges_count": 3,
    "recipes_count": 5,
    "strains_count": 8
  },
  "token": "a1b2c3d4e5f6..."
}
DELETE /api/v1/auth/logout

Invalidate the current API token. Requires authentication.

Example Request

curl -X DELETE https://fellowshipofthefork.com/api/v1/auth/logout \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{"message": "Logged out successfully"}
GET /api/v1/auth/me

Get the currently authenticated user's profile. Requires authentication.

Example Request

curl https://fellowshipofthefork.com/api/v1/auth/me \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{
  "user": {
    "id": 1,
    "username": "samwise",
    "email": "[email protected]",
    "display_name": "Samwise Gamgee",
    "bio": "Po-tay-toes enthusiast",
    "avatar_url": "/avatars/samwise.jpg",
    "points": 150,
    "admin": false,
    "age_verified": true,
    "terms_accepted": true,
    "badges_count": 3,
    "recipes_count": 5,
    "strains_count": 8,
    "preferences": {
      "profile_visible": true,
      "show_recipes": true,
      "show_strains": true
    },
    "created_at": "2026-01-15T10:30:00Z"
  }
}

Recipes

Create, browse, and manage cannabis edible recipes. Public recipes are accessible without authentication; creating and editing require a token.

GET /api/v1/recipes

List published recipes with filtering and sorting. No authentication required for public recipes.

Parameters

NameTypeRequiredDescription
searchstringNoSearch by recipe name or ingredients
categorystringNoFilter by recipe category
cannabis_typestringNoFilter by strain type (indica, sativa, hybrid, cbd_dominant)
difficultystringNoFilter by difficulty (easy, medium, hard)
min_dosagenumberNoMinimum mg THC per serving
max_dosagenumberNoMaximum mg THC per serving
dietary_tagsarrayNoFilter by dietary tags (e.g. vegan, gluten_free)
draftsbooleanNoIf true, show your draft recipes (auth required)
sortstringNoSort field: recipe_name, average_rating, ratings_count, calculated_dosage, created_at, difficulty, total_time, cost_per_serving
directionstringNoSort direction: asc or desc
per_pageintegerNoResults per page (default 10)

Example Request

curl "https://fellowshipofthefork.com/api/v1/recipes?category=brownies&sort=average_rating&direction=desc"

Example Response

{
  "recipes": [
    {
      "id": 1,
      "recipe_name": "Lembas Brownies",
      "slug": "lembas-brownies",
      "recipe_category": "brownies",
      "difficulty": "easy",
      "servings": 12,
      "prep_time": 15,
      "total_time": 45,
      "calculated_dosage": 10.5,
      "calculated_cbd_dosage": 0.5,
      "average_rating": 8.5,
      "ratings_count": 23,
      "forks_count": 3,
      "dietary_tags": ["gluten_free"],
      "total_cost": 25.00,
      "cost_per_serving": 2.08,
      "strain": {
        "id": 1,
        "strain_name": "Hobbit's Leaf",
        "cannabis_type": "hybrid"
      },
      "user": {
        "id": 1,
        "username": "samwise"
      },
      "created_at": "2026-01-20T14:00:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "total_pages": 3,
    "total_count": 25,
    "per_page": 10
  }
}
GET /api/v1/recipes/:id

Get full details for a single recipe including ratings, ingredients, and equipment.

Example Request

curl https://fellowshipofthefork.com/api/v1/recipes/1

Example Response

{
  "recipe": {
    "id": 1,
    "recipe_name": "Lembas Brownies",
    "slug": "lembas-brownies",
    "recipe_category": "brownies",
    "difficulty": "easy",
    "servings": 12,
    "prep_time": 15,
    "total_time": 45,
    "product_amount": 3.5,
    "decarb_method": "oven",
    "decarb_temperature": 240,
    "decarb_time": 40,
    "decarb_notes": "Watch for golden color",
    "infusion_method": "stovetop",
    "infusion_medium": "butter",
    "infusion_temperature": 180,
    "infusion_time": 120,
    "infusion_notes": "Low and slow",
    "ingredients": "1 cup cannabutter\n2 cups flour\n...",
    "instructions": "Step 1: Preheat oven...",
    "tips": "Let cool completely before cutting",
    "calculated_dosage": 10.5,
    "calculated_cbd_dosage": 0.5,
    "onset_time": 45,
    "personal_effects": "Relaxing body high",
    "average_rating": 8.5,
    "ratings_count": 23,
    "forks_count": 3,
    "dietary_tags": ["gluten_free"],
    "total_cost": 25.00,
    "cost_per_serving": 2.08,
    "cost_per_mg": 0.20,
    "strain": {
      "id": 1,
      "strain_name": "Hobbit's Leaf",
      "cannabis_type": "hybrid",
      "thc_percentage": 20.0,
      "cbd_percentage": 1.0
    },
    "user": {
      "id": 1,
      "username": "samwise"
    },
    "forked_from": null,
    "recipe_ingredients": [
      {"id": 1, "name": "Cannabutter", "link_url": null, "position": 1, "cost": 15.00}
    ],
    "recipe_equipments": [
      {"id": 1, "name": "Baking Pan", "link_url": null, "position": 1}
    ],
    "ratings": [
      {
        "id": 1,
        "rating": 9,
        "onset_time": 60,
        "effects": "Very relaxing",
        "comments": "Perfect dosage!",
        "user": {"id": 2, "username": "frodo"},
        "created_at": "2026-01-25T09:00:00Z"
      }
    ],
    "created_at": "2026-01-20T14:00:00Z"
  }
}
POST /api/v1/recipes

Create a new recipe. Requires authentication. Awards 50 points when published.

Parameters

NameTypeRequiredDescription
strain_idintegerYesID of the strain used
recipe_namestringYesName of the recipe
product_amountdecimalYesAmount of cannabis in grams
decarb_methodstringYesDecarb method (oven, sous_vide, instant_pot, etc.)
decarb_temperatureintegerYesTemperature in Fahrenheit
decarb_timeintegerYesDuration in minutes
decarb_notesstringNoNotes about decarboxylation
infusion_methodstringYesInfusion method (stovetop, crockpot, sous_vide, etc.)
infusion_mediumstringYesMedium (butter, coconut_oil, olive_oil, ghee, etc.)
infusion_temperatureintegerYesTemperature in Fahrenheit
infusion_timeintegerYesDuration in minutes
infusion_notesstringNoNotes about infusion
recipe_categorystringNoCategory (brownies, cookies, gummies, etc.)
ingredientstextYesIngredient list
instructionstextYesStep-by-step instructions
servingsintegerYesNumber of servings
onset_timeintegerNoExpected onset in minutes
personal_effectstextNoCreator's reported effects
tipstextNoTips and suggestions
difficultystringNoeasy, medium, or hard
prep_timeintegerNoPrep time in minutes
total_timeintegerNoTotal time in minutes
dietary_tagsarrayNoe.g. ["vegan", "gluten_free"]
draftbooleanNoSave as draft if true
recipe_ingredients_attributesarrayNoStructured ingredients with name, link_url, position, cost
recipe_equipments_attributesarrayNoEquipment items with name, link_url, position

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/recipes \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "strain_id": 1,
    "recipe_name": "Lembas Brownies",
    "product_amount": 3.5,
    "decarb_method": "oven",
    "decarb_temperature": 240,
    "decarb_time": 40,
    "infusion_method": "stovetop",
    "infusion_medium": "butter",
    "infusion_temperature": 180,
    "infusion_time": 120,
    "ingredients": "1 cup cannabutter\n2 cups flour",
    "instructions": "Preheat oven to 350F...",
    "servings": 12,
    "difficulty": "easy"
  }'
PATCH /api/v1/recipes/:id

Update an existing recipe. Only the recipe owner can update. Requires authentication.

Accepts the same parameters as create. Only include fields you want to change.

Example Request

curl -X PATCH https://fellowshipofthefork.com/api/v1/recipes/1 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"servings": 16, "tips": "Let cool completely"}'
DELETE /api/v1/recipes/:id

Delete a recipe. Only the recipe owner can delete. Requires authentication.

Example Request

curl -X DELETE https://fellowshipofthefork.com/api/v1/recipes/1 \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{"message": "Recipe deleted successfully"}
POST /api/v1/recipes/:id/fork

Create a copy of a recipe to customize. Awards points to both the original creator and the forker. Requires authentication.

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/recipes/1/fork \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{
  "recipe": {
    "id": 15,
    "recipe_name": "Lembas Brownies (Fork)",
    "forked_from": {
      "id": 1,
      "recipe_name": "Lembas Brownies"
    }
  },
  "message": "Recipe forked successfully"
}
GET /api/v1/recipes/:id/pdf

Download a printable PDF version of the recipe.

Example Request

curl -O https://fellowshipofthefork.com/api/v1/recipes/1/pdf

Returns a PDF file with Content-Type: application/pdf.

Recipe Ratings

Rate recipes and share your experience. One rating per user per recipe. All endpoints require authentication.

POST /api/v1/recipes/:recipe_id/ratings

Rate a recipe. Awards 5 points, plus 10 bonus points if you include effects. You cannot rate your own recipes.

Parameters

NameTypeRequiredDescription
ratingintegerYesRating from 1 to 10
onset_timeintegerNoYour onset time in minutes
effectsstringNoDescribe the effects you experienced
commentsstringNoAdditional comments

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/recipes/1/ratings \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "rating": 9,
    "onset_time": 45,
    "effects": "Relaxing body high, great for evening",
    "comments": "Perfect dosage, will make again!"
  }'

Example Response

{
  "rating": {
    "id": 1,
    "rating": 9,
    "onset_time": 45,
    "effects": "Relaxing body high, great for evening",
    "comments": "Perfect dosage, will make again!",
    "user": {"id": 2, "username": "frodo"},
    "recipe": {
      "id": 1,
      "recipe_name": "Lembas Brownies",
      "average_rating": 8.7,
      "ratings_count": 24
    },
    "created_at": "2026-01-25T09:00:00Z"
  }
}
PATCH /api/v1/recipes/:recipe_id/ratings/:id

Update your rating for a recipe. Requires authentication.

Accepts the same parameters as create.

Example Request

curl -X PATCH https://fellowshipofthefork.com/api/v1/recipes/1/ratings/1 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"rating": 10, "comments": "Even better the second time!"}'
DELETE /api/v1/recipes/:recipe_id/ratings/:id

Delete your rating. Requires authentication.

Example Request

curl -X DELETE https://fellowshipofthefork.com/api/v1/recipes/1/ratings/1 \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{"message": "Rating deleted successfully"}

Strains

Manage your personal strain library. All endpoints require authentication.

GET /api/v1/strains

List your strains with filtering and sorting.

Parameters

NameTypeRequiredDescription
product_typestringNoFilter: flower, wax, oil, edibles, tincture
cannabis_typestringNoFilter: indica, sativa, hybrid, cbd_dominant
favoritesbooleanNoIf true, show only favorites
sortstringNoSort field: strain_name, product_type, cannabis_type, thc_percentage, cbd_percentage, created_at
directionstringNoasc or desc
per_pageintegerNoResults per page

Example Request

curl "https://fellowshipofthefork.com/api/v1/strains?cannabis_type=hybrid&sort=thc_percentage&direction=desc" \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{
  "strains": [
    {
      "id": 1,
      "strain_name": "Hobbit's Leaf",
      "product_type": "flower",
      "cannabis_type": "hybrid",
      "thc_percentage": 20.0,
      "cbd_percentage": 1.0,
      "dispensary": "Green Dragon Dispensary",
      "favorite": true,
      "terpenes": {"myrcene": 0.5, "limonene": 0.3},
      "total_terpenes": 0.8,
      "slug": "hobbits-leaf",
      "created_at": "2026-01-10T08:00:00Z"
    }
  ],
  "meta": {"current_page": 1, "total_pages": 1, "total_count": 1, "per_page": 10}
}
GET /api/v1/strains/:id

Get full details for a strain including mood profile and recipe count.

Example Request

curl https://fellowshipofthefork.com/api/v1/strains/1 \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{
  "strain": {
    "id": 1,
    "strain_name": "Hobbit's Leaf",
    "product_type": "flower",
    "cannabis_type": "hybrid",
    "thc_percentage": 20.0,
    "cbd_percentage": 1.0,
    "dispensary": "Green Dragon Dispensary",
    "favorite": true,
    "terpenes": {"myrcene": 0.5, "limonene": 0.3},
    "total_terpenes": 0.8,
    "personal_notes": "Great for baking",
    "purchase_date": "2026-01-05",
    "mood_profile": {"relaxed": 7, "happy": 8, "creative": 6},
    "dominant_mood": "happy",
    "top_moods": [["happy", 8], ["relaxed", 7]],
    "recipes_count": 3,
    "slug": "hobbits-leaf",
    "created_at": "2026-01-10T08:00:00Z"
  }
}
POST /api/v1/strains

Add a new strain to your library. Awards 10 points.

Parameters

NameTypeRequiredDescription
strain_namestringYesName of the strain
product_typestringYesflower, wax, oil, edibles, or tincture
cannabis_typestringYesindica, sativa, hybrid, or cbd_dominant
thc_percentagedecimalNoTHC percentage (0-100)
cbd_percentagedecimalNoCBD percentage (0-100)
dispensarystringNoWhere purchased
personal_notesstringNoYour notes
purchase_datedateNoDate purchased (YYYY-MM-DD)
terpenesobjectNoTerpene profile as key-value pairs (e.g. {"myrcene": 0.5})

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/strains \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "strain_name": "Hobbit'\''s Leaf",
    "product_type": "flower",
    "cannabis_type": "hybrid",
    "thc_percentage": 20.0,
    "cbd_percentage": 1.0,
    "dispensary": "Green Dragon Dispensary",
    "terpenes": {"myrcene": 0.5, "limonene": 0.3}
  }'
PATCH /api/v1/strains/:id

Update a strain. Only the owner can update. Accepts the same parameters as create.

Example Request

curl -X PATCH https://fellowshipofthefork.com/api/v1/strains/1 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"thc_percentage": 22.5, "personal_notes": "Updated after lab test"}'
DELETE /api/v1/strains/:id

Delete a strain. Only the owner can delete.

Example Request

curl -X DELETE https://fellowshipofthefork.com/api/v1/strains/1 \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{"message": "Strain deleted successfully"}
PATCH /api/v1/strains/:id/toggle_favorite

Toggle the favorite status of a strain.

Example Request

curl -X PATCH https://fellowshipofthefork.com/api/v1/strains/1/toggle_favorite \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{
  "strain": {
    "id": 1,
    "strain_name": "Hobbit's Leaf",
    "favorite": true
  }
}

Users

View profiles, manage settings, and follow other users.

GET /api/v1/users/:id

Get a user's public profile. No authentication required, but auth adds follow status.

Example Request

curl https://fellowshipofthefork.com/api/v1/users/1

Example Response

{
  "user": {
    "id": 1,
    "username": "samwise",
    "display_name": "Samwise Gamgee",
    "bio": "Po-tay-toes enthusiast",
    "avatar_url": "/avatars/samwise.jpg",
    "points": 150,
    "followers_count": 12,
    "following_count": 5,
    "is_following": false,
    "badges": [
      {"id": 1, "badge_type": "chef", "badge_name": "One Recipe to Rule Them All", "created_at": "2026-01-20T14:00:00Z"}
    ],
    "recipes": [
      {"id": 1, "recipe_name": "Lembas Brownies", "slug": "lembas-brownies", "average_rating": 8.5}
    ],
    "strains": [
      {"id": 1, "strain_name": "Hobbit's Leaf", "cannabis_type": "hybrid"}
    ],
    "created_at": "2026-01-15T10:30:00Z"
  }
}
POST /api/v1/users/:id/follow

Follow a user. Requires authentication. You cannot follow yourself.

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/users/2/follow \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{"message": "Now following frodo", "followers_count": 8}
DELETE /api/v1/users/:id/follow

Unfollow a user. Requires authentication.

Example Request

curl -X DELETE https://fellowshipofthefork.com/api/v1/users/2/follow \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{"message": "Unfollowed frodo", "followers_count": 7}
PATCH /api/v1/users/settings

Update your account settings. Requires authentication.

Parameters

NameTypeRequiredDescription
emailstringNoNew email address
passwordstringNoNew password
password_confirmationstringNoMust match new password
display_namestringNoDisplay name
biostringNoBio text
avatar_datastringNoBase64-encoded avatar image (data URI)
preferencesobjectNoPrivacy settings
preferences.profile_visiblebooleanNoMake profile public
preferences.show_recipesbooleanNoShow recipes on profile
preferences.show_strainsbooleanNoShow strains on profile

Example Request

curl -X PATCH https://fellowshipofthefork.com/api/v1/users/settings \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Samwise Gamgee",
    "bio": "Po-tay-toes enthusiast",
    "preferences": {"profile_visible": true, "show_recipes": true}
  }'
DELETE /api/v1/users/account

Permanently delete your account and all associated data. Requires authentication. This action cannot be undone.

Example Request

curl -X DELETE https://fellowshipofthefork.com/api/v1/users/account \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{"message": "Account deleted successfully"}

Collections

Curate and organize recipes into themed collections.

GET /api/v1/collections

List public collections and your own private collections (if authenticated).

Parameters

NameTypeRequiredDescription
per_pageintegerNoResults per page

Example Request

curl https://fellowshipofthefork.com/api/v1/collections

Example Response

{
  "collections": [
    {
      "id": 1,
      "name": "Second Breakfast Favorites",
      "description": "Best recipes for morning edibles",
      "public": true,
      "slug": "second-breakfast-favorites",
      "recipes_count": 5,
      "user": {"id": 1, "username": "samwise"},
      "created_at": "2026-02-01T12:00:00Z"
    }
  ],
  "meta": {"current_page": 1, "total_pages": 1, "total_count": 3, "per_page": 10}
}
GET /api/v1/collections/:id

Get collection details with all recipes included.

Example Request

curl https://fellowshipofthefork.com/api/v1/collections/1
POST /api/v1/collections

Create a new collection. Awards 10 points. Requires authentication.

Parameters

NameTypeRequiredDescription
namestringYesCollection name
descriptionstringNoDescription
publicbooleanNoPublic visibility (default: true)

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/collections \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Second Breakfast Favorites", "description": "Morning edibles", "public": true}'
PATCH /api/v1/collections/:id

Update a collection. Owner only. Accepts the same parameters as create.

DELETE /api/v1/collections/:id

Delete a collection. Owner only. Requires authentication.

POST /api/v1/collections/:collection_id/collection_recipes

Add a recipe to a collection. Owner only. Requires authentication.

Parameters

NameTypeRequiredDescription
recipe_idintegerYesID of the recipe to add

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/collections/1/collection_recipes \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"recipe_id": 5}'

Example Response

{"message": "Recipe added to collection"}
DELETE /api/v1/collections/:collection_id/collection_recipes/:id

Remove a recipe from a collection. Owner only. Requires authentication.

Example Request

curl -X DELETE https://fellowshipofthefork.com/api/v1/collections/1/collection_recipes/3 \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{"message": "Recipe removed from collection"}

Dosage Calculator

Calculate THC/CBD dosages. All endpoints are public and require no authentication.

POST /api/v1/dosage_calculator/calculate

Calculate per-serving dosage from raw cannabis.

Parameters

NameTypeRequiredDescription
amountnumberYesAmount of cannabis (must be > 0)
unitstringNog (grams, default) or oz (ounces)
thc_percentagenumberYesTHC percentage
cbd_percentagenumberNoCBD percentage
servingsintegerYesNumber of servings (must be > 0)
decarb_methodstringNoDecarb method (affects efficiency)

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/dosage_calculator/calculate \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 3.5,
    "unit": "g",
    "thc_percentage": 20,
    "cbd_percentage": 1,
    "servings": 12
  }'

Example Response

{
  "results": {
    "thc_mg_per_serving": 52.5,
    "cbd_mg_per_serving": 2.63,
    "thc_mg_total": 630.0,
    "cbd_mg_total": 31.5,
    "input": {
      "amount": 3.5,
      "unit": "g",
      "thc_percentage": 20,
      "cbd_percentage": 1,
      "servings": 12
    }
  }
}
POST /api/v1/dosage_calculator/infusion

Calculate concentration per unit of infused medium (e.g. per cup of butter).

Parameters

NameTypeRequiredDescription
amountnumberYesAmount of cannabis
unitstringNog or oz
thc_percentagenumberYesTHC percentage
cbd_percentagenumberNoCBD percentage
decarb_methodstringNoDecarb method
volumenumberYesVolume of infusion medium
volume_unitstringNocup (default) or ml

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/dosage_calculator/infusion \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 7,
    "thc_percentage": 20,
    "volume": 2,
    "volume_unit": "cup"
  }'
POST /api/v1/dosage_calculator/recipe

Calculate per-serving dosage from a pre-made infusion.

Parameters

NameTypeRequiredDescription
infusion_amountnumberYesAmount of infusion used
infusion_unitstringNotsp (default) or ml
thc_per_tspnumberYesTHC mg per teaspoon of infusion
cbd_per_tspnumberNoCBD mg per teaspoon of infusion
servingsintegerYesNumber of servings

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/dosage_calculator/recipe \
  -H "Content-Type: application/json" \
  -d '{
    "infusion_amount": 4,
    "infusion_unit": "tsp",
    "thc_per_tsp": 25,
    "servings": 8
  }'

Badges

View your earned badges and total points. Requires authentication.

GET /api/v1/badges

List all badges earned by the authenticated user.

Example Request

curl https://fellowshipofthefork.com/api/v1/badges \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{
  "badges": [
    {
      "id": 1,
      "badge_type": "explorer",
      "badge_name": "Strained Relations",
      "description": "Created your first strain",
      "created_at": "2026-01-10T08:00:00Z"
    },
    {
      "id": 2,
      "badge_type": "chef",
      "badge_name": "One Recipe to Rule Them All",
      "description": "Created your first recipe",
      "created_at": "2026-01-20T14:00:00Z"
    }
  ],
  "total_points": 150
}

Feed

Activity feed showing actions from users you follow. Requires authentication.

GET /api/v1/feed

Get your personalized activity feed.

Parameters

NameTypeRequiredDescription
per_pageintegerNoResults per page (default 25)

Example Request

curl https://fellowshipofthefork.com/api/v1/feed \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{
  "activities": [
    {
      "id": 42,
      "action": "created_recipe",
      "user": {"id": 2, "username": "frodo"},
      "trackable_type": "Recipe",
      "trackable_id": 10,
      "metadata": {"recipe_name": "Elevenses Gummies"},
      "created_at": "2026-02-10T15:30:00Z"
    }
  ],
  "meta": {"current_page": 1, "total_pages": 2, "total_count": 35, "per_page": 25}
}

Terpene Matcher

Find recipes and strains that match your desired mood profile. No authentication required.

POST /api/v1/terpene_matcher/match

Get recipe and strain recommendations based on desired mood dimensions (rated 1-10).

Parameters

NameTypeRequiredDescription
mood[relaxed]integerNoRelaxation level (1-10, default 5)
mood[happy]integerNoHappiness level (1-10, default 5)
mood[creative]integerNoCreativity level (1-10, default 5)
mood[energetic]integerNoEnergy level (1-10, default 5)
mood[focused]integerNoFocus level (1-10, default 5)
mood[sleepy]integerNoSleepiness level (1-10, default 5)

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/terpene_matcher/match \
  -H "Content-Type: application/json" \
  -d '{"mood": {"relaxed": 8, "happy": 7, "creative": 3}}'

Example Response

{
  "recipe_matches": [
    {
      "recipe": {"id": 1, "name": "Lembas Brownies", "slug": "lembas-brownies"},
      "strain": {"id": 1, "name": "Hobbit's Leaf"},
      "similarity": 0.92,
      "mood_profile": {"relaxed": 9, "happy": 7, "creative": 4}
    }
  ],
  "strain_matches": [
    {
      "strain": {"id": 1, "name": "Hobbit's Leaf", "cannabis_type": "hybrid"},
      "similarity": 0.95,
      "mood_profile": {"relaxed": 9, "happy": 7, "creative": 4}
    }
  ]
}

Leaderboards

Community rankings and top content. No authentication required.

GET /api/v1/leaderboards

Get community leaderboards by time period.

Parameters

NameTypeRequiredDescription
periodstringNoweek, month, or all_time (default)

Example Request

curl "https://fellowshipofthefork.com/api/v1/leaderboards?period=month"

Example Response

{
  "top_fellows": [
    {"id": 1, "username": "samwise", "points": 500, "badge_count": 5}
  ],
  "top_recipes": [
    {"id": 1, "recipe_name": "Lembas Brownies", "slug": "lembas-brownies",
     "creator": "samwise", "average_rating": 9.2, "ratings_count": 30, "forks_count": 5}
  ],
  "most_forked": [
    {"id": 1, "recipe_name": "Lembas Brownies", "slug": "lembas-brownies",
     "creator": "samwise", "forks_count": 5}
  ],
  "rising_stars": [
    {"id": 3, "username": "pippin", "points": 120, "badge_count": 2}
  ]
}

Notifications

In-app notifications for activity on your content. All endpoints require authentication.

GET /api/v1/notifications

Get your notifications with unread count.

Parameters

NameTypeRequiredDescription
per_pageintegerNoResults per page (default 25)

Example Request

curl https://fellowshipofthefork.com/api/v1/notifications \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{
  "notifications": [
    {
      "id": 1,
      "action": "rated_recipe",
      "actor": {"id": 2, "username": "frodo", "display_name": "Frodo Baggins"},
      "notifiable_type": "Recipe",
      "notifiable_id": 1,
      "metadata": {},
      "read_at": null,
      "created_at": "2026-02-15T09:00:00Z"
    }
  ],
  "unread_count": 3,
  "meta": {"current_page": 1, "total_pages": 1, "total_count": 8, "per_page": 25}
}
PATCH /api/v1/notifications/:id/read

Mark a single notification as read.

Example Request

curl -X PATCH https://fellowshipofthefork.com/api/v1/notifications/1/read \
  -H "Authorization: Bearer YOUR_TOKEN"
PATCH /api/v1/notifications/read_all

Mark all notifications as read.

Example Request

curl -X PATCH https://fellowshipofthefork.com/api/v1/notifications/read_all \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{"message": "All notifications marked as read"}

Equipment

Browse the equipment catalog and manage reviews.

GET /api/v1/equipment

List available equipment. No authentication required.

Parameters

NameTypeRequiredDescription
categorystringNoFilter by category

Example Request

curl https://fellowshipofthefork.com/api/v1/equipment

Example Response

{
  "equipment": [
    {
      "id": 1,
      "name": "Magical Butter Machine",
      "slug": "magical-butter-machine",
      "description": "Automated infusion device",
      "category": "infusion",
      "affiliate_url": "https://example.com/...",
      "average_rating": 8.5,
      "reviews_count": 12
    }
  ]
}
GET /api/v1/equipment/:id

Get equipment details with reviews and recipe count. Uses slug as ID.

Example Request

curl https://fellowshipofthefork.com/api/v1/equipment/magical-butter-machine
POST /api/v1/equipment/:equipment_id/equipment_reviews

Review a piece of equipment. One review per user per equipment. Requires authentication.

Parameters

NameTypeRequiredDescription
equipment_review[rating]integerYesRating (1-10)
equipment_review[body]stringNoReview text

Example Request

curl -X POST https://fellowshipofthefork.com/api/v1/equipment/magical-butter-machine/equipment_reviews \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"equipment_review": {"rating": 9, "body": "Works perfectly for cannabutter"}}'
PATCH /api/v1/equipment/:equipment_id/equipment_reviews/:id

Update your review. Accepts the same parameters as create.

DELETE /api/v1/equipment/:equipment_id/equipment_reviews/:id

Delete your review. Requires authentication.

Quests

Time-limited community challenges. No authentication required, but auth adds your quest entry status.

GET /api/v1/quests/current

Get the currently active quest and your participation status.

Example Request

curl https://fellowshipofthefork.com/api/v1/quests/current \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{
  "quest": {
    "id": 1,
    "name": "The Great Brownie Bake-Off",
    "description": "Create and share a brownie recipe this week!",
    "quest_type": "recipe_creation",
    "bonus_points": 100,
    "start_date": "2026-02-17",
    "end_date": "2026-02-24"
  },
  "quest_entry": {
    "id": 5,
    "completed_at": "2026-02-18T14:30:00Z",
    "recipe_id": 15
  }
}