Overview

Events are the activity log for your garden. Record watering, harvests, fertilizing, pruning, and other care activities for each plot. Events power XP calculations, achievement tracking, and care streak gamification.

Event Types

TypeDescriptionXP
wateringWatered the plot5
harvestHarvested produce (includes weight data)15
fertilizeApplied fertilizer or amendments10
prunePruned or deadheaded plants10
sowSowed seeds directly in the plot10
transplantTransplanted a seedling into the plot15
pestNoted or treated pest/disease issue5
noteGeneral observation or note5
mulchApplied mulch10
weedWeeded the plot10
trainTrained, staked, or trellised plants10
thinThinned seedlings5

Endpoints

MethodPathDescriptionAuth Required
GET/plots/:id/eventsList events for a plotYes
POST/plots/:id/eventsCreate an eventYes
GET/events/:idGet event detailsYes
PUT/events/:idUpdate an eventYes
DELETE/events/:idDelete an eventYes

List Events

Retrieve events for a specific plot, with optional filtering.

GET /plots/:plotId/events

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number
per_pageinteger20Items per page (max 100)
event_typestringFilter by event type
start_datestringFilter events after this date (RFC 3339)
end_datestringFilter events before this date (RFC 3339)

Response 200 OK

{
  "data": [
    {
      "id": "evt_a1b2c3d4",
      "plot_id": "plt_m3n4o5p6",
      "event_type": "harvest",
      "title": "Tomato Harvest",
      "notes": "First harvest of the season! Beautiful Cherokee Purples.",
      "quantity_grams": 1250,
      "quality_rating": 5,
      "photos": [
        {
          "id": "pht_x1y2z3",
          "url": "https://cdn.garden.gg/events/pht_x1y2z3.jpg",
          "thumbnail_url": "https://cdn.garden.gg/events/pht_x1y2z3_thumb.jpg"
        }
      ],
      "xp_earned": 15,
      "created_at": "2026-07-20T18:30:00Z",
      "updated_at": "2026-07-20T18:30:00Z"
    },
    {
      "id": "evt_e5f6g7h8",
      "plot_id": "plt_m3n4o5p6",
      "event_type": "watering",
      "title": "Morning watering",
      "notes": "Deep watering, soil was dry 2 inches down",
      "quantity_grams": null,
      "quality_rating": null,
      "photos": [],
      "xp_earned": 5,
      "created_at": "2026-07-20T07:00:00Z",
      "updated_at": "2026-07-20T07:00:00Z"
    }
  ],
  "total": 47,
  "page": 1,
  "per_page": 20
}

Examples

cURL

# List all harvest events for a plot
curl -X GET "https://garden.gg/api/v1/plots/plt_m3n4o5p6/events?event_type=harvest" \
  -H "Authorization: Bearer gg_live_your_api_key_here"

# Filter events by date range
curl -X GET "https://garden.gg/api/v1/plots/plt_m3n4o5p6/events?start_date=2026-07-01T00:00:00Z&end_date=2026-07-31T23:59:59Z" \
  -H "Authorization: Bearer gg_live_your_api_key_here"

Python

import requests

headers = {"Authorization": "Bearer gg_live_your_api_key_here"}

# Get all harvest events
response = requests.get(
    "https://garden.gg/api/v1/plots/plt_m3n4o5p6/events",
    headers=headers,
    params={"event_type": "harvest"},
)

events = response.json()
total_grams = sum(e["quantity_grams"] for e in events["data"] if e["quantity_grams"])
print(f"Total harvested: {total_grams}g from {events['total']} harvests")

Node.js

const params = new URLSearchParams({
  event_type: "harvest",
  start_date: "2026-07-01T00:00:00Z",
  end_date: "2026-07-31T23:59:59Z",
});

const response = await fetch(
  `https://garden.gg/api/v1/plots/plt_m3n4o5p6/events?${params.toString()}`,
  { headers: { Authorization: "Bearer gg_live_your_api_key_here" } }
);

const { data: events, total } = await response.json();
console.log(`${total} harvest events in July`);

Create Event

Log a new garden activity event.

POST /plots/:plotId/events

Request Body

FieldTypeRequiredDescription
event_typestringYesOne of the supported event types (see above)
titlestringYesShort title for the event (1-200 characters)
notesstringNoDetailed notes
quantity_gramsintegerNoWeight in grams (harvest events)
quality_ratingintegerNoQuality rating 1-5 (harvest events)

For harvest events, quantity_grams and quality_rating are strongly recommended.

Request

{
  "event_type": "harvest",
  "title": "Tomato Harvest",
  "notes": "First harvest of the season! Beautiful Cherokee Purples.",
  "quantity_grams": 1250,
  "quality_rating": 5
}

Response 201 Created

{
  "id": "evt_i9j0k1l2",
  "plot_id": "plt_m3n4o5p6",
  "event_type": "harvest",
  "title": "Tomato Harvest",
  "notes": "First harvest of the season! Beautiful Cherokee Purples.",
  "quantity_grams": 1250,
  "quality_rating": 5,
  "photos": [],
  "xp_earned": 15,
  "created_at": "2026-07-20T18:30:00Z",
  "updated_at": "2026-07-20T18:30:00Z"
}

Photo Upload

To attach photos to an event, use a multipart form data request:

curl -X POST "https://garden.gg/api/v1/plots/plt_m3n4o5p6/events" \
  -H "Authorization: Bearer gg_live_your_api_key_here" \
  -F "event_type=harvest" \
  -F "title=Tomato Harvest" \
  -F "quantity_grams=1250" \
  -F "quality_rating=5" \
  -F "photos[][email protected]" \
  -F "photos[][email protected]"

Photos are automatically resized and thumbnails are generated. Supported formats: JPEG, PNG, WebP. Maximum file size: 10MB per photo, 5 photos per event.

Examples

cURL

# Log a watering event
curl -X POST "https://garden.gg/api/v1/plots/plt_m3n4o5p6/events" \
  -H "Authorization: Bearer gg_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "watering",
    "title": "Evening watering",
    "notes": "Deep watering before expected heat wave"
  }'

Python

import requests

headers = {
    "Authorization": "Bearer gg_live_your_api_key_here",
    "Content-Type": "application/json",
}

# Log a fertilizing event
response = requests.post(
    "https://garden.gg/api/v1/plots/plt_m3n4o5p6/events",
    headers=headers,
    json={
        "event_type": "fertilize",
        "title": "Fish emulsion feed",
        "notes": "Applied 5-1-1 fish emulsion, diluted per label",
    },
)

event = response.json()
print(f"Logged event: {event['title']} (+{event['xp_earned']} XP)")

Python (with photo upload)

import requests

headers = {"Authorization": "Bearer gg_live_your_api_key_here"}

with open("harvest.jpg", "rb") as photo:
    response = requests.post(
        "https://garden.gg/api/v1/plots/plt_m3n4o5p6/events",
        headers=headers,
        data={
            "event_type": "harvest",
            "title": "Basil harvest",
            "quantity_grams": 200,
            "quality_rating": 4,
        },
        files={"photos[]": ("harvest.jpg", photo, "image/jpeg")},
    )

event = response.json()
print(f"Logged harvest with {len(event['photos'])} photo(s)")

Node.js

const response = await fetch(
  "https://garden.gg/api/v1/plots/plt_m3n4o5p6/events",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer gg_live_your_api_key_here",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      event_type: "pest",
      title: "Aphid outbreak",
      notes: "Found aphids on pepper plants. Applied neem oil spray.",
    }),
  }
);

const event = await response.json();
console.log(`Logged: ${event.title} (+${event.xp_earned} XP)`);

Get Event

Retrieve details for a single event.

GET /events/:id

Response 200 OK

Returns a full event object (same structure as in the list response).

Update Event

Update an existing event.

PUT /events/:id

Request Body

FieldTypeRequiredDescription
titlestringNoEvent title
notesstringNoDetailed notes
quantity_gramsintegerNoWeight in grams
quality_ratingintegerNoQuality rating 1-5

The event_type cannot be changed after creation.

Response 200 OK

Returns the full updated event object.

Delete Event

Delete an event. XP earned from this event will be deducted from your total.

DELETE /events/:id

Response 204 No Content

No response body.

Error Responses

ScenarioHTTP StatusError Code
Event not found404NOT_FOUND
Plot not found404NOT_FOUND
Invalid event type400VALIDATION_ERROR
Missing required fields400VALIDATION_ERROR
Invalid quality rating400VALIDATION_ERROR
Photo too large (>10MB)400VALIDATION_ERROR
Too many photos (>5)400VALIDATION_ERROR
Not your event403FORBIDDEN
Not authenticated401UNAUTHORIZED