Cheese Store

v2.0.0

Welcome to the Cheese Store API reference. This is a live example of how you can use Sourcey to generate beautiful static documentation for your APIs.

The Cheese Store API is organized around REST. It uses resource-oriented URLs, standard HTTP methods, and returns JSON responses. All requests are authenticated using an API key or OAuth2 token.

Getting Started

  1. Sign up for a developer account at cheesy.sourcey.com
  2. Generate an API key from your dashboard
  3. Include the key in your requests as X-API-Key header

Rate Limiting

Plan Requests/hour Burst
Free 100 10
Pro 10,000 100
Enterprise Unlimited 1,000

When you exceed the rate limit, the API returns 429 Too Many Requests with a Retry-After header.

Pagination

List endpoints return paginated results. Use cursor and limit query parameters:

{
  "items": [...],
  "nextCursor": "eyJpZCI6NDJ9",
  "hasMore": true
}

Hard cheese gouda say cheese. Ricotta cauliflower cheese cheesecake bocconcini edam bocconcini fromage feta. Who moved my cheese bocconcini cheese and wine cottage cheese cheese on toast who moved my cheese caerphilly stinking bishop. Bocconcini cheesy feet the big cheese macaroni cheese cheesy feet mascarpone.

Terms of Service

Contact: cheesy@sourcey.com

Base URLs
https://cheesy.sourcey.com/v2Production
https://sandbox.cheesy.sourcey.com/v2Sandbox (test data, rate limits relaxed)
http://localhost:3000/v2Local development

Authentication

api_keyapiKey

API key authentication. Include your API key in the X-API-Key header.

Get your key from the developer dashboard.

API Key: X-API-Key in header

cheesy_oauthoauth2

OAuth2 authentication for full API access

implicit

Authorization: https://cheesy.sourcey.com/oauth/authorize

Scopes: read:cheeses — Read cheese data, write:cheeses — Create and update cheeses, read:orders — View order history, write:orders — Place and manage orders

authorizationCode

Authorization: https://cheesy.sourcey.com/oauth/authorize

Token: https://cheesy.sourcey.com/oauth/token

Scopes: read:cheeses — Read cheese data, write:cheeses — Create and update cheeses, read:orders — View order history, write:orders — Place and manage orders

bearer_authhttp

JWT token obtained from the /customer/login endpoint

Scheme: bearer (JWT)

Cheese

Cheese endpoints provide access to information and operations relating to the cheeses available in the store.

Cheeses can be filtered by status, tags, and category. Each cheese has a unique ID, name, category, and availability status.

List all cheeses

GET
https://cheesy.sourcey.com/v2/cheeses

Returns a paginated list of cheeses in the store. Results can be filtered by status and sorted by name or creation date.

The response includes cursor-based pagination. Use the nextCursor value from the response as the cursor parameter in subsequent requests.

Parameters

cursorstringquery

Pagination cursor from a previous response

limitinteger[1, 100]20query

Maximum number of cheeses to return

statusstringavailablependingsoldquery

Filter by availability status

sortstringname-namecreatedAt-createdAtnamequery

Sort order for results

Response

200OKobject

A paginated list of cheeses

429Too Many Requestsobject

Rate limit exceeded

Authorization

api_keyapiKey in header

API key authentication. Include your API key in the X-API-Key header.

Get your key from the developer dashboard.

cheesy_oauthoauth2

OAuth2 authentication for full API access

Scopes: read:cheeses

List all cheeses
curl -X GET 'https://cheesy.sourcey.com/v2/cheeses'
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses', {
  method: 'GET',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses', {
  method: 'GET',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.get('https://cheesy.sourcey.com/v2/cheeses')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "https://cheesy.sourcey.com/v2/cheeses", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/cheeses')
request = Net::HTTP::Get.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.get("https://cheesy.sourcey.com/v2/cheeses")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
{
  "items": [
    {
      "id": 42,
      "name": "Gorgonzola",
      "category": {
        "id": 1,
        "name": "Italian Cheese"
      },
      "photoUrls": [
        "https://wannabechef.com/gorgonzola.jpg"
      ],
      "tags": [
        {
          "id": 1,
          "name": "blue"
        }
      ],
      "status": "available",
      "origin": "Italy",
      "pricePerKg": 28.5,
      "ageMonths": 12,
      "organic": false,
      "createdAt": "2024-01-15T09:30:00Z",
      "updatedAt": "2024-01-15T09:30:00Z"
    }
  ],
  "nextCursor": "string",
  "hasMore": true,
  "total": 0
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

Add a new cheese

POST
https://cheesy.sourcey.com/v2/cheeses

Add a new cheese to the store inventory. The cheese name must be unique within its category.

Body

application/json

Cheese object to add to the store

namestringrequired
categoryobject
Show child attributes
namestring
photoUrlsArray<string>
tagsArray<object>
Show child attributes
namestring
statusstringavailablependingsoldavailable
originstring | null
pricePerKgnumber<float>
ageMonthsinteger[0, 120]
organicbooleanfalse

Response

201Createdobject

Cheese created successfully

409Conflictobject

A cheese with this name already exists in the category

422Unprocessable Entityobject

The request body failed validation

Authorization

cheesy_oauthoauth2

OAuth2 authentication for full API access

Scopes: write:cheeses

Add a new cheese
curl -X POST 'https://cheesy.sourcey.com/v2/cheeses' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Gorgonzola",
    "category": {
      "name": "Italian Cheese"
    },
    "status": "available",
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "name": "blue"
      },
      {
        "name": "italian"
      },
      {
        "name": "creamy"
      }
    ]
  }'
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "name": "Gorgonzola",
      "category": {
        "name": "Italian Cheese"
      },
      "status": "available",
      "photoUrls": [
        "https://wannabechef.com/gorgonzola.jpg"
      ],
      "tags": [
        {
          "name": "blue"
        },
        {
          "name": "italian"
        },
        {
          "name": "creamy"
        }
      ]
    }),
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "name": "Gorgonzola",
      "category": {
        "name": "Italian Cheese"
      },
      "status": "available",
      "photoUrls": [
        "https://wannabechef.com/gorgonzola.jpg"
      ],
      "tags": [
        {
          "name": "blue"
        },
        {
          "name": "italian"
        },
        {
          "name": "creamy"
        }
      ]
    }),
});

const data: Record<string, unknown> = await response.json();
import requests

payload = {
  "name": "Gorgonzola",
  "category": {
    "name": "Italian Cheese"
  },
  "status": "available",
  "photoUrls": [
    "https://wannabechef.com/gorgonzola.jpg"
  ],
  "tags": [
    {
      "name": "blue"
    },
    {
      "name": "italian"
    },
    {
      "name": "creamy"
    }
  ]
}

response = requests.post('https://cheesy.sourcey.com/v2/cheeses', json=payload)
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "name": "Gorgonzola",
    "category": {
      "name": "Italian Cheese"
    },
    "status": "available",
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "name": "blue"
      },
      {
        "name": "italian"
      },
      {
        "name": "creamy"
      }
    ]
  }`)
  req, _ := http.NewRequest("POST", "https://cheesy.sourcey.com/v2/cheeses", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/cheeses')
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = '{
    "name": "Gorgonzola",
    "category": {
      "name": "Italian Cheese"
    },
    "status": "available",
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "name": "blue"
      },
      {
        "name": "italian"
      },
      {
        "name": "creamy"
      }
    ]
  }'

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let body = serde_json::json!({
      "name": "Gorgonzola",
      "category": {
        "name": "Italian Cheese"
      },
      "status": "available",
      "photoUrls": [
        "https://wannabechef.com/gorgonzola.jpg"
      ],
      "tags": [
        {
          "name": "blue"
        },
        {
          "name": "italian"
        },
        {
          "name": "creamy"
        }
      ]
    });
    let response = client.post("https://cheesy.sourcey.com/v2/cheeses")
        .json(&body)
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
Request Body
{
  "name": "string",
  "category": {
    "name": "string"
  },
  "photoUrls": [
    "https://example.com"
  ],
  "tags": [
    {
      "name": "string"
    }
  ],
  "status": "available",
  "origin": "string",
  "pricePerKg": 0,
  "ageMonths": 0,
  "organic": false
}
{
  "id": 42,
  "name": "Gorgonzola",
  "category": {
    "id": 1,
    "name": "Italian Cheese"
  },
  "photoUrls": [
    "https://wannabechef.com/gorgonzola.jpg"
  ],
  "tags": [
    {
      "id": 1,
      "name": "blue"
    }
  ],
  "status": "available",
  "origin": "Italy",
  "pricePerKg": 28.5,
  "ageMonths": 12,
  "organic": false,
  "createdAt": "2024-01-15T09:30:00Z",
  "updatedAt": "2024-01-15T09:30:00Z"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}
{
  "code": 422,
  "type": "Validation error",
  "message": "Your cheese is not mouldy enough",
  "errors": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}

Update an existing cheese

PUT
https://cheesy.sourcey.com/v2/cheeses

Replace an existing cheese with updated data. The cheese ID in the body must match an existing cheese.

Body

application/json

Cheese object with updated fields

idinteger<int64>required

Unique identifier

namestringrequired

Name of the cheese

categoryobject
Show child attributes
idinteger<int64>
namestring
photoUrlsArray<string>

URLs of cheese photos

tagsArray<object>

Classification tags

Show child attributes
idinteger<int64>
namestring
statusstringavailablependingsoldrequired

Availability status in the store

originstring | null

Country of origin (null if unknown)

pricePerKgnumber<float>

Price per kilogram in USD

ageMonthsinteger[0, 120]

Aging period in months

organicbooleanfalse

Whether the cheese is certified organic

createdAtstring<date-time>

When the cheese was added to the store

updatedAtstring<date-time>

When the cheese was last updated

Response

200OKobject

Cheese updated successfully

404Not Foundobject

The requested resource was not found

422Unprocessable Entityobject

The request body failed validation

Authorization

cheesy_oauthoauth2

OAuth2 authentication for full API access

Scopes: write:cheeses

Update an existing cheese
curl -X PUT 'https://cheesy.sourcey.com/v2/cheeses' \
  -H 'Content-Type: application/json' \
  -d '{
    "id": 42,
    "name": "Gorgonzola",
    "category": {
      "id": 1,
      "name": "Italian Cheese"
    },
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "id": 1,
        "name": "blue"
      }
    ],
    "status": "available",
    "origin": "Italy",
    "pricePerKg": 28.5,
    "ageMonths": 12,
    "organic": false,
    "createdAt": "2024-01-15T09:30:00Z",
    "updatedAt": "2024-01-15T09:30:00Z"
  }'
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "id": 42,
      "name": "Gorgonzola",
      "category": {
        "id": 1,
        "name": "Italian Cheese"
      },
      "photoUrls": [
        "https://wannabechef.com/gorgonzola.jpg"
      ],
      "tags": [
        {
          "id": 1,
          "name": "blue"
        }
      ],
      "status": "available",
      "origin": "Italy",
      "pricePerKg": 28.5,
      "ageMonths": 12,
      "organic": false,
      "createdAt": "2024-01-15T09:30:00Z",
      "updatedAt": "2024-01-15T09:30:00Z"
    }),
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "id": 42,
      "name": "Gorgonzola",
      "category": {
        "id": 1,
        "name": "Italian Cheese"
      },
      "photoUrls": [
        "https://wannabechef.com/gorgonzola.jpg"
      ],
      "tags": [
        {
          "id": 1,
          "name": "blue"
        }
      ],
      "status": "available",
      "origin": "Italy",
      "pricePerKg": 28.5,
      "ageMonths": 12,
      "organic": false,
      "createdAt": "2024-01-15T09:30:00Z",
      "updatedAt": "2024-01-15T09:30:00Z"
    }),
});

const data: Record<string, unknown> = await response.json();
import requests

payload = {
  "id": 42,
  "name": "Gorgonzola",
  "category": {
    "id": 1,
    "name": "Italian Cheese"
  },
  "photoUrls": [
    "https://wannabechef.com/gorgonzola.jpg"
  ],
  "tags": [
    {
      "id": 1,
      "name": "blue"
    }
  ],
  "status": "available",
  "origin": "Italy",
  "pricePerKg": 28.5,
  "ageMonths": 12,
  "organic": False,
  "createdAt": "2024-01-15T09:30:00Z",
  "updatedAt": "2024-01-15T09:30:00Z"
}

response = requests.put('https://cheesy.sourcey.com/v2/cheeses', json=payload)
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "id": 42,
    "name": "Gorgonzola",
    "category": {
      "id": 1,
      "name": "Italian Cheese"
    },
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "id": 1,
        "name": "blue"
      }
    ],
    "status": "available",
    "origin": "Italy",
    "pricePerKg": 28.5,
    "ageMonths": 12,
    "organic": false,
    "createdAt": "2024-01-15T09:30:00Z",
    "updatedAt": "2024-01-15T09:30:00Z"
  }`)
  req, _ := http.NewRequest("PUT", "https://cheesy.sourcey.com/v2/cheeses", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/cheeses')
request = Net::HTTP::Put.new(uri)
request['Content-Type'] = 'application/json'
request.body = '{
    "id": 42,
    "name": "Gorgonzola",
    "category": {
      "id": 1,
      "name": "Italian Cheese"
    },
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "id": 1,
        "name": "blue"
      }
    ],
    "status": "available",
    "origin": "Italy",
    "pricePerKg": 28.5,
    "ageMonths": 12,
    "organic": false,
    "createdAt": "2024-01-15T09:30:00Z",
    "updatedAt": "2024-01-15T09:30:00Z"
  }'

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let body = serde_json::json!({
      "id": 42,
      "name": "Gorgonzola",
      "category": {
        "id": 1,
        "name": "Italian Cheese"
      },
      "photoUrls": [
        "https://wannabechef.com/gorgonzola.jpg"
      ],
      "tags": [
        {
          "id": 1,
          "name": "blue"
        }
      ],
      "status": "available",
      "origin": "Italy",
      "pricePerKg": 28.5,
      "ageMonths": 12,
      "organic": false,
      "createdAt": "2024-01-15T09:30:00Z",
      "updatedAt": "2024-01-15T09:30:00Z"
    });
    let response = client.put("https://cheesy.sourcey.com/v2/cheeses")
        .json(&body)
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
Request Body
{
  "id": 42,
  "name": "Gorgonzola",
  "category": {
    "id": 1,
    "name": "Italian Cheese"
  },
  "photoUrls": [
    "https://wannabechef.com/gorgonzola.jpg"
  ],
  "tags": [
    {
      "id": 1,
      "name": "blue"
    }
  ],
  "status": "available",
  "origin": "Italy",
  "pricePerKg": 28.5,
  "ageMonths": 12,
  "organic": false,
  "createdAt": "2024-01-15T09:30:00Z",
  "updatedAt": "2024-01-15T09:30:00Z"
}
{
  "id": 42,
  "name": "Gorgonzola",
  "category": {
    "id": 1,
    "name": "Italian Cheese"
  },
  "photoUrls": [
    "https://wannabechef.com/gorgonzola.jpg"
  ],
  "tags": [
    {
      "id": 1,
      "name": "blue"
    }
  ],
  "status": "available",
  "origin": "Italy",
  "pricePerKg": 28.5,
  "ageMonths": 12,
  "organic": false,
  "createdAt": "2024-01-15T09:30:00Z",
  "updatedAt": "2024-01-15T09:30:00Z"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}
{
  "code": 422,
  "type": "Validation error",
  "message": "Your cheese is not mouldy enough",
  "errors": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}

Find cheeses by status

GET
https://cheesy.sourcey.com/v2/cheeses/findByStatus

Multiple status values can be provided as comma-separated strings. Returns all cheeses matching any of the given statuses.

Parameters

statusArray<string>availablependingsoldrequiredquery

Status values to filter by

Response

200OKArray<object>

Matching cheeses

400Bad Requestobject

Invalid status value provided

Authorization

cheesy_oauthoauth2

OAuth2 authentication for full API access

Scopes: read:cheeses

Find cheeses by status
curl -X GET 'https://cheesy.sourcey.com/v2/cheeses/findByStatus'
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/findByStatus', {
  method: 'GET',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/findByStatus', {
  method: 'GET',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.get('https://cheesy.sourcey.com/v2/cheeses/findByStatus')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "https://cheesy.sourcey.com/v2/cheeses/findByStatus", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/cheeses/findByStatus')
request = Net::HTTP::Get.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.get("https://cheesy.sourcey.com/v2/cheeses/findByStatus")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
[
  {
    "id": 42,
    "name": "Gorgonzola",
    "category": {
      "id": 1,
      "name": "Italian Cheese"
    },
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "id": 1,
        "name": "blue"
      }
    ],
    "status": "available",
    "origin": "Italy",
    "pricePerKg": 28.5,
    "ageMonths": 12,
    "organic": false,
    "createdAt": "2024-01-15T09:30:00Z",
    "updatedAt": "2024-01-15T09:30:00Z"
  }
]
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

Find cheeses by tags

deprecated
GET
https://cheesy.sourcey.com/v2/cheeses/findByTags

Multiple tags can be provided as comma-separated strings (e.g. ?tags=blue,italian,aged).

Deprecated: Use GET /cheeses?tags=blue,italian query parameter instead.

Parameters

tagsArray<string>requiredquery

Tags to filter by

Response

200OKArray<object>

Matching cheeses

400Bad Requestobject

Invalid tag value

Authorization

cheesy_oauthoauth2

OAuth2 authentication for full API access

Scopes: read:cheeses

Find cheeses by tags
curl -X GET 'https://cheesy.sourcey.com/v2/cheeses/findByTags'
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/findByTags', {
  method: 'GET',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/findByTags', {
  method: 'GET',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.get('https://cheesy.sourcey.com/v2/cheeses/findByTags')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "https://cheesy.sourcey.com/v2/cheeses/findByTags", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/cheeses/findByTags')
request = Net::HTTP::Get.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.get("https://cheesy.sourcey.com/v2/cheeses/findByTags")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
[
  {
    "id": 42,
    "name": "Gorgonzola",
    "category": {
      "id": 1,
      "name": "Italian Cheese"
    },
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "id": 1,
        "name": "blue"
      }
    ],
    "status": "available",
    "origin": "Italy",
    "pricePerKg": 28.5,
    "ageMonths": 12,
    "organic": false,
    "createdAt": "2024-01-15T09:30:00Z",
    "updatedAt": "2024-01-15T09:30:00Z"
  }
]
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

Get cheese by ID

GET
https://cheesy.sourcey.com/v2/cheeses/{cheeseId}

Returns detailed information about a specific cheese, including its category, tags, and current availability status.

Parameters

cheeseIdinteger<int64>requiredpath

Unique identifier for the cheese

Response

200OKobject

Cheese details

404Not Foundobject

The requested resource was not found

Authorization

api_keyapiKey in header

API key authentication. Include your API key in the X-API-Key header.

Get your key from the developer dashboard.

Get cheese by ID
curl -X GET 'https://cheesy.sourcey.com/v2/cheeses/{cheeseId}'
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}', {
  method: 'GET',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}', {
  method: 'GET',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.get('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "https://cheesy.sourcey.com/v2/cheeses/{cheeseId}", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}')
request = Net::HTTP::Get.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.get("https://cheesy.sourcey.com/v2/cheeses/{cheeseId}")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
{
  "id": 42,
  "name": "Gorgonzola",
  "category": {
    "id": 1,
    "name": "Italian Cheese"
  },
  "photoUrls": [
    "https://wannabechef.com/gorgonzola.jpg"
  ],
  "tags": [
    {
      "id": 1,
      "name": "blue"
    }
  ],
  "status": "available",
  "origin": "Italy",
  "pricePerKg": 28.5,
  "ageMonths": 12,
  "organic": false,
  "createdAt": "2024-01-15T09:30:00Z",
  "updatedAt": "2024-01-15T09:30:00Z"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

Update cheese with form data

POST
https://cheesy.sourcey.com/v2/cheeses/{cheeseId}

Updates specific fields of a cheese using form data. Only provided fields are updated.

Parameters

cheeseIdinteger<int64>requiredpath

Unique identifier for the cheese

namestringquery

Updated name of the cheese

statusstringavailablependingsoldquery

Updated status of the cheese

Response

200OKobject

Cheese updated

404Not Foundobject

The requested resource was not found

422Unprocessable Entityobject

The request body failed validation

Authorization

cheesy_oauthoauth2

OAuth2 authentication for full API access

Scopes: write:cheeses

Update cheese with form data
curl -X POST 'https://cheesy.sourcey.com/v2/cheeses/{cheeseId}'
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}', {
  method: 'POST',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}', {
  method: 'POST',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.post('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("POST", "https://cheesy.sourcey.com/v2/cheeses/{cheeseId}", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}')
request = Net::HTTP::Post.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.post("https://cheesy.sourcey.com/v2/cheeses/{cheeseId}")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
{
  "id": 42,
  "name": "Gorgonzola",
  "category": {
    "id": 1,
    "name": "Italian Cheese"
  },
  "photoUrls": [
    "https://wannabechef.com/gorgonzola.jpg"
  ],
  "tags": [
    {
      "id": 1,
      "name": "blue"
    }
  ],
  "status": "available",
  "origin": "Italy",
  "pricePerKg": 28.5,
  "ageMonths": 12,
  "organic": false,
  "createdAt": "2024-01-15T09:30:00Z",
  "updatedAt": "2024-01-15T09:30:00Z"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}
{
  "code": 422,
  "type": "Validation error",
  "message": "Your cheese is not mouldy enough",
  "errors": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}

Delete a cheese

DELETE
https://cheesy.sourcey.com/v2/cheeses/{cheeseId}

Permanently removes a cheese from the store. This action cannot be undone. Any pending orders for this cheese will be cancelled.

Parameters

cheeseIdinteger<int64>requiredpath

Unique identifier for the cheese

X-Confirm-Deletebooleanrequiredheader

Must be set to true to confirm deletion

Response

204No Content

Cheese deleted successfully

404Not Foundobject

The requested resource was not found

409Conflictobject

Cheese has active orders and cannot be deleted

Authorization

cheesy_oauthoauth2

OAuth2 authentication for full API access

Scopes: write:cheeses

Delete a cheese
curl -X DELETE 'https://cheesy.sourcey.com/v2/cheeses/{cheeseId}'
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}', {
  method: 'DELETE',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}', {
  method: 'DELETE',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.delete('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("DELETE", "https://cheesy.sourcey.com/v2/cheeses/{cheeseId}", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}')
request = Net::HTTP::Delete.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.delete("https://cheesy.sourcey.com/v2/cheeses/{cheeseId}")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

Upload a cheese image

POST
https://cheesy.sourcey.com/v2/cheeses/{cheeseId}/uploadImage

Upload a photo of the cheese. Supports JPEG, PNG, and WebP formats. Maximum file size is 10MB.

Body

multipart/form-data
filestring<binary>required

Image file (JPEG, PNG, or WebP, max 10MB)

captionstring

Optional caption for the image

isPrimarybooleanfalse

Set as the primary display image

Parameters

cheeseIdinteger<int64>requiredpath

ID of cheese to upload image for

Response

200OKobject

Image uploaded successfully

413Payload Too Largeobject

File too large (max 10MB)

415Unsupported Media Typeobject

Unsupported media type

Authorization

cheesy_oauthoauth2

OAuth2 authentication for full API access

Scopes: write:cheeses

Upload a cheese image
curl -X POST 'https://cheesy.sourcey.com/v2/cheeses/{cheeseId}/uploadImage' \
  -H 'Content-Type: multipart/form-data' \
  -d '{
    "file": "<binary>",
    "caption": "string",
    "isPrimary": false
  }'
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}/uploadImage', {
  method: 'POST',
  headers: {
    'Content-Type': 'multipart/form-data',
  },
  body: JSON.stringify({
      "file": "<binary>",
      "caption": "string",
      "isPrimary": false
    }),
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}/uploadImage', {
  method: 'POST',
  headers: {
    'Content-Type': 'multipart/form-data',
  },
  body: JSON.stringify({
      "file": "<binary>",
      "caption": "string",
      "isPrimary": false
    }),
});

const data: Record<string, unknown> = await response.json();
import requests

payload = {
  "file": "<binary>",
  "caption": "string",
  "isPrimary": False
}

response = requests.post('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}/uploadImage', json=payload)
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "file": "<binary>",
    "caption": "string",
    "isPrimary": false
  }`)
  req, _ := http.NewRequest("POST", "https://cheesy.sourcey.com/v2/cheeses/{cheeseId}/uploadImage", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/cheeses/{cheeseId}/uploadImage')
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'multipart/form-data'
request.body = '{
    "file": "<binary>",
    "caption": "string",
    "isPrimary": false
  }'

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let body = serde_json::json!({
      "file": "<binary>",
      "caption": "string",
      "isPrimary": false
    });
    let response = client.post("https://cheesy.sourcey.com/v2/cheeses/{cheeseId}/uploadImage")
        .json(&body)
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
Request Body
{
  "file": "<binary>",
  "caption": "string",
  "isPrimary": false
}
{
  "imageUrl": "https://example.com",
  "thumbnailUrl": "https://example.com",
  "size": 0
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

Store

Store endpoints provide access to cheese store orders and inventory management. Orders track the purchase lifecycle from placement through delivery.

Get store inventory

GET
https://cheesy.sourcey.com/v2/store/inventory

Returns a map of cheese status codes to quantities, representing the current inventory levels.

Response

200OKobject

Inventory counts by status

Authorization

api_keyapiKey in header

API key authentication. Include your API key in the X-API-Key header.

Get your key from the developer dashboard.

Get store inventory
curl -X GET 'https://cheesy.sourcey.com/v2/store/inventory'
const response = await fetch('https://cheesy.sourcey.com/v2/store/inventory', {
  method: 'GET',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/store/inventory', {
  method: 'GET',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.get('https://cheesy.sourcey.com/v2/store/inventory')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "https://cheesy.sourcey.com/v2/store/inventory", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/store/inventory')
request = Net::HTTP::Get.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.get("https://cheesy.sourcey.com/v2/store/inventory")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
200
{}

Place a cheese order

POST
https://cheesy.sourcey.com/v2/store/order

Place an order to purchase cheese from the store. The cheese must be in available status.

Orders are processed asynchronously. Use the returned order ID to check status via GET /store/order/{orderId}.

Body

application/json

Order details

itemsArray<object>required
Show child attributes
cheeseIdinteger<int64>required
quantityinteger[1, 100]required
shippingAddressobjectrequired
Show child attributes
streetstringrequired
citystringrequired
statestring | null
zipCodestring
countrystringrequired

ISO 3166-1 alpha-2 country code

notesstring | null

Response

201Createdobject

Order placed successfully

422Unprocessable Entityobject

The request body failed validation

Authorization

cheesy_oauthoauth2

OAuth2 authentication for full API access

Scopes: write:orders

Place a cheese order
curl -X POST 'https://cheesy.sourcey.com/v2/store/order' \
  -H 'Content-Type: application/json' \
  -d '{
    "items": [
      {
        "cheeseId": 42,
        "quantity": 3
      },
      {
        "cheeseId": 17,
        "quantity": 1
      }
    ],
    "shippingAddress": {
      "street": "123 Cheese Lane",
      "city": "Cheddarville",
      "state": "WI",
      "zipCode": "53001",
      "country": "US"
    },
    "notes": "Please wrap each wheel separately"
  }'
const response = await fetch('https://cheesy.sourcey.com/v2/store/order', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "items": [
        {
          "cheeseId": 42,
          "quantity": 3
        },
        {
          "cheeseId": 17,
          "quantity": 1
        }
      ],
      "shippingAddress": {
        "street": "123 Cheese Lane",
        "city": "Cheddarville",
        "state": "WI",
        "zipCode": "53001",
        "country": "US"
      },
      "notes": "Please wrap each wheel separately"
    }),
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/store/order', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "items": [
        {
          "cheeseId": 42,
          "quantity": 3
        },
        {
          "cheeseId": 17,
          "quantity": 1
        }
      ],
      "shippingAddress": {
        "street": "123 Cheese Lane",
        "city": "Cheddarville",
        "state": "WI",
        "zipCode": "53001",
        "country": "US"
      },
      "notes": "Please wrap each wheel separately"
    }),
});

const data: Record<string, unknown> = await response.json();
import requests

payload = {
  "items": [
    {
      "cheeseId": 42,
      "quantity": 3
    },
    {
      "cheeseId": 17,
      "quantity": 1
    }
  ],
  "shippingAddress": {
    "street": "123 Cheese Lane",
    "city": "Cheddarville",
    "state": "WI",
    "zipCode": "53001",
    "country": "US"
  },
  "notes": "Please wrap each wheel separately"
}

response = requests.post('https://cheesy.sourcey.com/v2/store/order', json=payload)
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "items": [
      {
        "cheeseId": 42,
        "quantity": 3
      },
      {
        "cheeseId": 17,
        "quantity": 1
      }
    ],
    "shippingAddress": {
      "street": "123 Cheese Lane",
      "city": "Cheddarville",
      "state": "WI",
      "zipCode": "53001",
      "country": "US"
    },
    "notes": "Please wrap each wheel separately"
  }`)
  req, _ := http.NewRequest("POST", "https://cheesy.sourcey.com/v2/store/order", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/store/order')
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = '{
    "items": [
      {
        "cheeseId": 42,
        "quantity": 3
      },
      {
        "cheeseId": 17,
        "quantity": 1
      }
    ],
    "shippingAddress": {
      "street": "123 Cheese Lane",
      "city": "Cheddarville",
      "state": "WI",
      "zipCode": "53001",
      "country": "US"
    },
    "notes": "Please wrap each wheel separately"
  }'

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let body = serde_json::json!({
      "items": [
        {
          "cheeseId": 42,
          "quantity": 3
        },
        {
          "cheeseId": 17,
          "quantity": 1
        }
      ],
      "shippingAddress": {
        "street": "123 Cheese Lane",
        "city": "Cheddarville",
        "state": "WI",
        "zipCode": "53001",
        "country": "US"
      },
      "notes": "Please wrap each wheel separately"
    });
    let response = client.post("https://cheesy.sourcey.com/v2/store/order")
        .json(&body)
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
Request Body
{
  "items": [
    {
      "cheeseId": 0,
      "quantity": 1
    }
  ],
  "shippingAddress": {
    "street": "123 Cheese Lane",
    "city": "Cheddarville",
    "state": "WI",
    "zipCode": "53001",
    "country": "US"
  },
  "notes": "string"
}
{
  "id": 1001,
  "items": [
    {
      "cheeseId": 42,
      "cheeseName": "Gorgonzola",
      "quantity": 3,
      "pricePerKg": 28.5
    },
    {
      "cheeseId": 17,
      "cheeseName": "Brie",
      "quantity": 1,
      "pricePerKg": 22
    }
  ],
  "shippingAddress": {
    "street": "123 Cheese Lane",
    "city": "Cheddarville",
    "state": "WI",
    "zipCode": "53001",
    "country": "US"
  },
  "status": "placed",
  "notes": "Please wrap each wheel separately",
  "total": 114.5,
  "shipDate": null,
  "createdAt": "2026-03-10T14:30:00Z",
  "updatedAt": "2026-03-10T14:30:00Z"
}
{
  "code": 422,
  "type": "Validation error",
  "message": "Your cheese is not mouldy enough",
  "errors": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}

Get order by ID

GET
https://cheesy.sourcey.com/v2/store/order/{orderId}

Retrieve details of a specific order. For testing, use order IDs between 1 and 10.

Parameters

orderIdinteger<int64>requiredpath

ID of the order

Response

200OKobject

Order details

404Not Foundobject

The requested resource was not found

Authorization

api_keyapiKey in header

API key authentication. Include your API key in the X-API-Key header.

Get your key from the developer dashboard.

Get order by ID
curl -X GET 'https://cheesy.sourcey.com/v2/store/order/{orderId}'
const response = await fetch('https://cheesy.sourcey.com/v2/store/order/{orderId}', {
  method: 'GET',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/store/order/{orderId}', {
  method: 'GET',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.get('https://cheesy.sourcey.com/v2/store/order/{orderId}')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "https://cheesy.sourcey.com/v2/store/order/{orderId}", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/store/order/{orderId}')
request = Net::HTTP::Get.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.get("https://cheesy.sourcey.com/v2/store/order/{orderId}")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
{
  "id": 1001,
  "items": [
    {
      "cheeseId": 42,
      "cheeseName": "Gorgonzola",
      "quantity": 3,
      "pricePerKg": 28.5
    },
    {
      "cheeseId": 17,
      "cheeseName": "Brie",
      "quantity": 1,
      "pricePerKg": 22
    }
  ],
  "shippingAddress": {
    "street": "123 Cheese Lane",
    "city": "Cheddarville",
    "state": "WI",
    "zipCode": "53001",
    "country": "US"
  },
  "status": "placed",
  "notes": "Please wrap each wheel separately",
  "total": 114.5,
  "shipDate": null,
  "createdAt": "2026-03-10T14:30:00Z",
  "updatedAt": "2026-03-10T14:30:00Z"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

Cancel an order

DELETE
https://cheesy.sourcey.com/v2/store/order/{orderId}

Cancel a pending order. Orders that have already been shipped cannot be cancelled.

Parameters

orderIdinteger<int64>requiredpath

ID of the order

Response

204No Content

Order cancelled successfully

404Not Foundobject

The requested resource was not found

409Conflictobject

Order has already been shipped

Authorization

cheesy_oauthoauth2

OAuth2 authentication for full API access

Scopes: write:orders

Cancel an order
curl -X DELETE 'https://cheesy.sourcey.com/v2/store/order/{orderId}'
const response = await fetch('https://cheesy.sourcey.com/v2/store/order/{orderId}', {
  method: 'DELETE',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/store/order/{orderId}', {
  method: 'DELETE',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.delete('https://cheesy.sourcey.com/v2/store/order/{orderId}')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("DELETE", "https://cheesy.sourcey.com/v2/store/order/{orderId}", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/store/order/{orderId}')
request = Net::HTTP::Delete.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.delete("https://cheesy.sourcey.com/v2/store/order/{orderId}")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

Customer

Customer endpoints handle account creation, authentication, and profile management.

Customer accounts support OAuth2 login and API key authentication.

Create a customer account

POST
https://cheesy.sourcey.com/v2/customer

Register a new customer account. The username and email must be unique.

Body

application/json

Customer registration details

usernamestringrequired
firstNamestring
lastNamestring
emailstring<email>required
passwordstring<password>required
phonestring | null

Response

201Createdobject

Customer account created

409Conflictobject

Username or email already exists

422Unprocessable Entityobject

The request body failed validation

Create a customer account
curl -X POST 'https://cheesy.sourcey.com/v2/customer' \
  -H 'Content-Type: application/json' \
  -d '{
    "username": "gordo",
    "firstName": "Alotta",
    "lastName": "Cheese",
    "email": "love@cheese.com",
    "password": "secret123!",
    "phone": "+3344556677"
  }'
const response = await fetch('https://cheesy.sourcey.com/v2/customer', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "username": "gordo",
      "firstName": "Alotta",
      "lastName": "Cheese",
      "email": "love@cheese.com",
      "password": "secret123!",
      "phone": "+3344556677"
    }),
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/customer', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "username": "gordo",
      "firstName": "Alotta",
      "lastName": "Cheese",
      "email": "love@cheese.com",
      "password": "secret123!",
      "phone": "+3344556677"
    }),
});

const data: Record<string, unknown> = await response.json();
import requests

payload = {
  "username": "gordo",
  "firstName": "Alotta",
  "lastName": "Cheese",
  "email": "love@cheese.com",
  "password": "secret123!",
  "phone": "+3344556677"
}

response = requests.post('https://cheesy.sourcey.com/v2/customer', json=payload)
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "username": "gordo",
    "firstName": "Alotta",
    "lastName": "Cheese",
    "email": "love@cheese.com",
    "password": "secret123!",
    "phone": "+3344556677"
  }`)
  req, _ := http.NewRequest("POST", "https://cheesy.sourcey.com/v2/customer", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/customer')
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = '{
    "username": "gordo",
    "firstName": "Alotta",
    "lastName": "Cheese",
    "email": "love@cheese.com",
    "password": "secret123!",
    "phone": "+3344556677"
  }'

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let body = serde_json::json!({
      "username": "gordo",
      "firstName": "Alotta",
      "lastName": "Cheese",
      "email": "love@cheese.com",
      "password": "secret123!",
      "phone": "+3344556677"
    });
    let response = client.post("https://cheesy.sourcey.com/v2/customer")
        .json(&body)
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
Request Body
{
  "username": "string",
  "firstName": "string",
  "lastName": "string",
  "email": "user@example.com",
  "password": "********",
  "phone": "string"
}
{
  "id": 1,
  "username": "gordo",
  "firstName": "Alotta",
  "lastName": "Cheese",
  "email": "love@cheese.com",
  "phone": "+3344556677",
  "customerStatus": "gold",
  "favouriteCheese": {
    "id": 42,
    "name": "Gorgonzola",
    "category": {
      "id": 1,
      "name": "Italian Cheese"
    },
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "id": 1,
        "name": "blue"
      }
    ],
    "status": "available",
    "origin": "Italy",
    "pricePerKg": 28.5,
    "ageMonths": 12,
    "organic": false,
    "createdAt": "2024-01-15T09:30:00Z",
    "updatedAt": "2024-01-15T09:30:00Z"
  },
  "createdAt": "2024-01-15T09:30:00Z"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}
{
  "code": 422,
  "type": "Validation error",
  "message": "Your cheese is not mouldy enough",
  "errors": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}

Create multiple customers

POST
https://cheesy.sourcey.com/v2/customer/createMultiple

Create a batch of customer accounts from an array. Each customer is validated independently - partial success is possible.

Returns the created customers and any validation errors:

{
  "created": [...],
  "errors": [
    { "index": 2, "message": "Email already exists" }
  ]
}

Body

application/json

Array of customer objects to create

Array<object>
Show child attributes
usernamestringrequired
firstNamestring
lastNamestring
emailstring<email>required
passwordstring<password>required
phonestring | null

Response

200OKobject

Batch creation result

422Unprocessable Entityobject

The request body failed validation

Create multiple customers
curl -X POST 'https://cheesy.sourcey.com/v2/customer/createMultiple' \
  -H 'Content-Type: application/json' \
  -d '[
    {
      "username": "string",
      "firstName": "string",
      "lastName": "string",
      "email": "user@example.com",
      "password": "********",
      "phone": "string"
    }
  ]'
const response = await fetch('https://cheesy.sourcey.com/v2/customer/createMultiple', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify([
      {
        "username": "string",
        "firstName": "string",
        "lastName": "string",
        "email": "user@example.com",
        "password": "********",
        "phone": "string"
      }
    ]),
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/customer/createMultiple', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify([
      {
        "username": "string",
        "firstName": "string",
        "lastName": "string",
        "email": "user@example.com",
        "password": "********",
        "phone": "string"
      }
    ]),
});

const data: Record<string, unknown> = await response.json();
import requests

payload = [
  {
    "username": "string",
    "firstName": "string",
    "lastName": "string",
    "email": "user@example.com",
    "password": "********",
    "phone": "string"
  }
]

response = requests.post('https://cheesy.sourcey.com/v2/customer/createMultiple', json=payload)
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`[
    {
      "username": "string",
      "firstName": "string",
      "lastName": "string",
      "email": "user@example.com",
      "password": "********",
      "phone": "string"
    }
  ]`)
  req, _ := http.NewRequest("POST", "https://cheesy.sourcey.com/v2/customer/createMultiple", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/customer/createMultiple')
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = '[
    {
      "username": "string",
      "firstName": "string",
      "lastName": "string",
      "email": "user@example.com",
      "password": "********",
      "phone": "string"
    }
  ]'

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let body = serde_json::json!([
      {
        "username": "string",
        "firstName": "string",
        "lastName": "string",
        "email": "user@example.com",
        "password": "********",
        "phone": "string"
      }
    ]);
    let response = client.post("https://cheesy.sourcey.com/v2/customer/createMultiple")
        .json(&body)
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
Request Body
[
  {
    "username": "string",
    "firstName": "string",
    "lastName": "string",
    "email": "user@example.com",
    "password": "********",
    "phone": "string"
  }
]
{
  "created": [
    {
      "id": 1,
      "username": "gordo",
      "firstName": "Alotta",
      "lastName": "Cheese",
      "email": "love@cheese.com",
      "phone": "+3344556677",
      "customerStatus": "gold",
      "favouriteCheese": {
        "id": 42,
        "name": "Gorgonzola",
        "category": {
          "id": 1,
          "name": "Italian Cheese"
        },
        "photoUrls": [
          "https://wannabechef.com/gorgonzola.jpg"
        ],
        "tags": [
          {
            "id": 1,
            "name": "blue"
          }
        ],
        "status": "available",
        "origin": "Italy",
        "pricePerKg": 28.5,
        "ageMonths": 12,
        "organic": false,
        "createdAt": "2024-01-15T09:30:00Z",
        "updatedAt": "2024-01-15T09:30:00Z"
      },
      "createdAt": "2024-01-15T09:30:00Z"
    }
  ],
  "errors": [
    {
      "index": 0,
      "message": "string"
    }
  ]
}
{
  "code": 422,
  "type": "Validation error",
  "message": "Your cheese is not mouldy enough",
  "errors": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}

Customer login

POST
https://cheesy.sourcey.com/v2/customer/login

Authenticate a customer and receive a session token. The token expires after 24 hours.

Body

application/json
usernamestringrequired

The customer's username

passwordstring<password>required

The customer's password

Response

200OKobject

Login successful

401Unauthorizedobject

Invalid username or password

Customer login
curl -X POST 'https://cheesy.sourcey.com/v2/customer/login' \
  -H 'Content-Type: application/json' \
  -d '{
    "username": "string",
    "password": "********"
  }'
const response = await fetch('https://cheesy.sourcey.com/v2/customer/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "username": "string",
      "password": "********"
    }),
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/customer/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "username": "string",
      "password": "********"
    }),
});

const data: Record<string, unknown> = await response.json();
import requests

payload = {
  "username": "string",
  "password": "********"
}

response = requests.post('https://cheesy.sourcey.com/v2/customer/login', json=payload)
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "username": "string",
    "password": "********"
  }`)
  req, _ := http.NewRequest("POST", "https://cheesy.sourcey.com/v2/customer/login", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/customer/login')
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = '{
    "username": "string",
    "password": "********"
  }'

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let body = serde_json::json!({
      "username": "string",
      "password": "********"
    });
    let response = client.post("https://cheesy.sourcey.com/v2/customer/login")
        .json(&body)
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
Request Body
{
  "username": "string",
  "password": "********"
}
{
  "token": "string",
  "expiresAt": "2024-01-15T09:30:00Z"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

Customer logout

GET
https://cheesy.sourcey.com/v2/customer/logout

End the current customer session and invalidate the session token.

Response

204No Content

Logout successful

Authorization

bearer_authhttp (bearer)

JWT token obtained from the /customer/login endpoint

Customer logout
curl -X GET 'https://cheesy.sourcey.com/v2/customer/logout'
const response = await fetch('https://cheesy.sourcey.com/v2/customer/logout', {
  method: 'GET',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/customer/logout', {
  method: 'GET',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.get('https://cheesy.sourcey.com/v2/customer/logout')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "https://cheesy.sourcey.com/v2/customer/logout", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/customer/logout')
request = Net::HTTP::Get.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.get("https://cheesy.sourcey.com/v2/customer/logout")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}

Get customer by username

GET
https://cheesy.sourcey.com/v2/customer/{username}

Retrieve a customer's profile by their username.

Parameters

usernamestringrequiredpath

The customer's username

Response

200OKobject

Customer profile

404Not Foundobject

The requested resource was not found

Authorization

api_keyapiKey in header

API key authentication. Include your API key in the X-API-Key header.

Get your key from the developer dashboard.

bearer_authhttp (bearer)

JWT token obtained from the /customer/login endpoint

Get customer by username
curl -X GET 'https://cheesy.sourcey.com/v2/customer/{username}'
const response = await fetch('https://cheesy.sourcey.com/v2/customer/{username}', {
  method: 'GET',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/customer/{username}', {
  method: 'GET',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.get('https://cheesy.sourcey.com/v2/customer/{username}')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "https://cheesy.sourcey.com/v2/customer/{username}", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/customer/{username}')
request = Net::HTTP::Get.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.get("https://cheesy.sourcey.com/v2/customer/{username}")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
{
  "id": 1,
  "username": "gordo",
  "firstName": "Alotta",
  "lastName": "Cheese",
  "email": "love@cheese.com",
  "phone": "+3344556677",
  "customerStatus": "gold",
  "favouriteCheese": {
    "id": 42,
    "name": "Gorgonzola",
    "category": {
      "id": 1,
      "name": "Italian Cheese"
    },
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "id": 1,
        "name": "blue"
      }
    ],
    "status": "available",
    "origin": "Italy",
    "pricePerKg": 28.5,
    "ageMonths": 12,
    "organic": false,
    "createdAt": "2024-01-15T09:30:00Z",
    "updatedAt": "2024-01-15T09:30:00Z"
  },
  "createdAt": "2024-01-15T09:30:00Z"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

Update customer profile

PUT
https://cheesy.sourcey.com/v2/customer/{username}

Update a customer's profile. Can only be performed by the authenticated customer.

Body

application/json

Updated customer fields

usernamestringrequired
firstNamestring
lastNamestring
emailstring<email>required
passwordstring<password>required
phonestring | null

Parameters

usernamestringrequiredpath

The customer's username

Response

200OKobject

Customer updated

404Not Foundobject

The requested resource was not found

422Unprocessable Entityobject

The request body failed validation

Authorization

bearer_authhttp (bearer)

JWT token obtained from the /customer/login endpoint

Update customer profile
curl -X PUT 'https://cheesy.sourcey.com/v2/customer/{username}' \
  -H 'Content-Type: application/json' \
  -d '{
    "username": "string",
    "firstName": "string",
    "lastName": "string",
    "email": "user@example.com",
    "password": "********",
    "phone": "string"
  }'
const response = await fetch('https://cheesy.sourcey.com/v2/customer/{username}', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "username": "string",
      "firstName": "string",
      "lastName": "string",
      "email": "user@example.com",
      "password": "********",
      "phone": "string"
    }),
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/customer/{username}', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "username": "string",
      "firstName": "string",
      "lastName": "string",
      "email": "user@example.com",
      "password": "********",
      "phone": "string"
    }),
});

const data: Record<string, unknown> = await response.json();
import requests

payload = {
  "username": "string",
  "firstName": "string",
  "lastName": "string",
  "email": "user@example.com",
  "password": "********",
  "phone": "string"
}

response = requests.put('https://cheesy.sourcey.com/v2/customer/{username}', json=payload)
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "username": "string",
    "firstName": "string",
    "lastName": "string",
    "email": "user@example.com",
    "password": "********",
    "phone": "string"
  }`)
  req, _ := http.NewRequest("PUT", "https://cheesy.sourcey.com/v2/customer/{username}", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/customer/{username}')
request = Net::HTTP::Put.new(uri)
request['Content-Type'] = 'application/json'
request.body = '{
    "username": "string",
    "firstName": "string",
    "lastName": "string",
    "email": "user@example.com",
    "password": "********",
    "phone": "string"
  }'

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let body = serde_json::json!({
      "username": "string",
      "firstName": "string",
      "lastName": "string",
      "email": "user@example.com",
      "password": "********",
      "phone": "string"
    });
    let response = client.put("https://cheesy.sourcey.com/v2/customer/{username}")
        .json(&body)
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
Request Body
{
  "username": "string",
  "firstName": "string",
  "lastName": "string",
  "email": "user@example.com",
  "password": "********",
  "phone": "string"
}
{
  "id": 1,
  "username": "gordo",
  "firstName": "Alotta",
  "lastName": "Cheese",
  "email": "love@cheese.com",
  "phone": "+3344556677",
  "customerStatus": "gold",
  "favouriteCheese": {
    "id": 42,
    "name": "Gorgonzola",
    "category": {
      "id": 1,
      "name": "Italian Cheese"
    },
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "id": 1,
        "name": "blue"
      }
    ],
    "status": "available",
    "origin": "Italy",
    "pricePerKg": 28.5,
    "ageMonths": 12,
    "organic": false,
    "createdAt": "2024-01-15T09:30:00Z",
    "updatedAt": "2024-01-15T09:30:00Z"
  },
  "createdAt": "2024-01-15T09:30:00Z"
}
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}
{
  "code": 422,
  "type": "Validation error",
  "message": "Your cheese is not mouldy enough",
  "errors": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}

Delete customer account

DELETE
https://cheesy.sourcey.com/v2/customer/{username}

Permanently delete a customer account and all associated data. This action cannot be undone.

Parameters

usernamestringrequiredpath

The customer's username

Response

204No Content

Customer deleted

404Not Foundobject

The requested resource was not found

Authorization

bearer_authhttp (bearer)

JWT token obtained from the /customer/login endpoint

Delete customer account
curl -X DELETE 'https://cheesy.sourcey.com/v2/customer/{username}'
const response = await fetch('https://cheesy.sourcey.com/v2/customer/{username}', {
  method: 'DELETE',
});

const data = await response.json();
const response = await fetch('https://cheesy.sourcey.com/v2/customer/{username}', {
  method: 'DELETE',
});

const data: Record<string, unknown> = await response.json();
import requests

response = requests.delete('https://cheesy.sourcey.com/v2/customer/{username}')
data = response.json()
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("DELETE", "https://cheesy.sourcey.com/v2/customer/{username}", nil)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
require 'net/http'
require 'json'

uri = URI('https://cheesy.sourcey.com/v2/customer/{username}')
request = Net::HTTP::Delete.new(uri)

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
data = JSON.parse(response.body)
use reqwest;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::new();
    let response = client.delete("https://cheesy.sourcey.com/v2/customer/{username}")
        .send()
        .await?
        .text()
        .await?;
    println!("{}", response);
    Ok(())
}
404
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

Models

Cheese

object
idinteger<int64>required

Unique identifier

namestringrequired

Name of the cheese

categoryobject
Show child attributes
idinteger<int64>
namestring
photoUrlsArray<string>

URLs of cheese photos

tagsArray<object>

Classification tags

Show child attributes
idinteger<int64>
namestring
statusstringavailablependingsoldrequired

Availability status in the store

originstring | null

Country of origin (null if unknown)

pricePerKgnumber<float>

Price per kilogram in USD

ageMonthsinteger[0, 120]

Aging period in months

organicbooleanfalse

Whether the cheese is certified organic

createdAtstring<date-time>

When the cheese was added to the store

updatedAtstring<date-time>

When the cheese was last updated

Example
{
  "id": 42,
  "name": "Gorgonzola",
  "category": {
    "id": 1,
    "name": "Italian Cheese"
  },
  "photoUrls": [
    "https://wannabechef.com/gorgonzola.jpg"
  ],
  "tags": [
    {
      "id": 1,
      "name": "blue"
    }
  ],
  "status": "available",
  "origin": "Italy",
  "pricePerKg": 28.5,
  "ageMonths": 12,
  "organic": false,
  "createdAt": "2024-01-15T09:30:00Z",
  "updatedAt": "2024-01-15T09:30:00Z"
}

CheeseInput

object
namestringrequired
categoryobject
Show child attributes
namestring
photoUrlsArray<string>
tagsArray<object>
Show child attributes
namestring
statusstringavailablependingsoldavailable
originstring | null
pricePerKgnumber<float>
ageMonthsinteger[0, 120]
organicbooleanfalse
Example
{
  "name": "string",
  "category": {
    "name": "string"
  },
  "photoUrls": [
    "https://example.com"
  ],
  "tags": [
    {
      "name": "string"
    }
  ],
  "status": "available",
  "origin": "string",
  "pricePerKg": 0,
  "ageMonths": 0,
  "organic": false
}

CheeseList

object

Paginated list of cheeses

itemsArray<object>
Show child attributes
idinteger<int64>required

Unique identifier

namestringrequired

Name of the cheese

categoryobject
Show child attributes
idinteger<int64>
namestring
photoUrlsArray<string>

URLs of cheese photos

tagsArray<object>

Classification tags

Show child attributes
idinteger<int64>
namestring
statusstringavailablependingsoldrequired

Availability status in the store

originstring | null

Country of origin (null if unknown)

pricePerKgnumber<float>

Price per kilogram in USD

ageMonthsinteger[0, 120]

Aging period in months

organicbooleanfalse

Whether the cheese is certified organic

createdAtstring<date-time>

When the cheese was added to the store

updatedAtstring<date-time>

When the cheese was last updated

nextCursorstring | null

Cursor for the next page (null if no more results)

hasMoreboolean

Whether there are more results

totalinteger

Total number of matching cheeses

Example
{
  "items": [
    {
      "id": 42,
      "name": "Gorgonzola",
      "category": {
        "id": 1,
        "name": "Italian Cheese"
      },
      "photoUrls": [
        "https://wannabechef.com/gorgonzola.jpg"
      ],
      "tags": [
        {
          "id": 1,
          "name": "blue"
        }
      ],
      "status": "available",
      "origin": "Italy",
      "pricePerKg": 28.5,
      "ageMonths": 12,
      "organic": false,
      "createdAt": "2024-01-15T09:30:00Z",
      "updatedAt": "2024-01-15T09:30:00Z"
    }
  ],
  "nextCursor": "string",
  "hasMore": true,
  "total": 0
}

Category

object
idinteger<int64>
namestring
Example
{
  "id": 1,
  "name": "Italian Cheese"
}

Tag

object
idinteger<int64>
namestring
Example
{
  "id": 1,
  "name": "blue"
}

Order

object
idinteger<int64>
itemsArray<object>
Show child attributes
cheeseIdinteger<int64>
cheeseNamestring
quantityinteger
pricePerKgnumber<float>
shippingAddressobject
Show child attributes
streetstringrequired
citystringrequired
statestring | null
zipCodestring
countrystringrequired

ISO 3166-1 alpha-2 country code

statusstringplacedapprovedshippeddeliveredcancelled

Order lifecycle status

notesstring | null

Special instructions for the order

totalnumber<float>

Order total in USD

shipDatestring<date-time> | null

Estimated ship date (null if not yet scheduled)

createdAtstring<date-time>
updatedAtstring<date-time>
Example
{
  "id": 1001,
  "items": [
    {
      "cheeseId": 42,
      "cheeseName": "Gorgonzola",
      "quantity": 3,
      "pricePerKg": 28.5
    },
    {
      "cheeseId": 17,
      "cheeseName": "Brie",
      "quantity": 1,
      "pricePerKg": 22
    }
  ],
  "shippingAddress": {
    "street": "123 Cheese Lane",
    "city": "Cheddarville",
    "state": "WI",
    "zipCode": "53001",
    "country": "US"
  },
  "status": "placed",
  "notes": "Please wrap each wheel separately",
  "total": 114.5,
  "shipDate": null,
  "createdAt": "2026-03-10T14:30:00Z",
  "updatedAt": "2026-03-10T14:30:00Z"
}

OrderInput

object
itemsArray<object>required
Show child attributes
cheeseIdinteger<int64>required
quantityinteger[1, 100]required
shippingAddressobjectrequired
Show child attributes
streetstringrequired
citystringrequired
statestring | null
zipCodestring
countrystringrequired

ISO 3166-1 alpha-2 country code

notesstring | null
Example
{
  "items": [
    {
      "cheeseId": 0,
      "quantity": 1
    }
  ],
  "shippingAddress": {
    "street": "123 Cheese Lane",
    "city": "Cheddarville",
    "state": "WI",
    "zipCode": "53001",
    "country": "US"
  },
  "notes": "string"
}

OrderItem

object
cheeseIdinteger<int64>
cheeseNamestring
quantityinteger
pricePerKgnumber<float>
Example
{
  "cheeseId": 0,
  "cheeseName": "string",
  "quantity": 1,
  "pricePerKg": 0
}

Address

object
streetstringrequired
citystringrequired
statestring | null
zipCodestring
countrystringrequired

ISO 3166-1 alpha-2 country code

Example
{
  "street": "123 Cheese Lane",
  "city": "Cheddarville",
  "state": "WI",
  "zipCode": "53001",
  "country": "US"
}

Customer

object
idinteger<int64>
usernamestring
firstNamestring

Customer first name

lastNamestring

Customer last name

emailstring<email>
phonestring | null
customerStatusstringbronzesilvergoldplatinum

Customer tier based on purchase volume

favouriteCheeseobject | object

The customer's favourite cheese (by reference or by name)

createdAtstring<date-time>
Example
{
  "id": 1,
  "username": "gordo",
  "firstName": "Alotta",
  "lastName": "Cheese",
  "email": "love@cheese.com",
  "phone": "+3344556677",
  "customerStatus": "gold",
  "favouriteCheese": {
    "id": 42,
    "name": "Gorgonzola",
    "category": {
      "id": 1,
      "name": "Italian Cheese"
    },
    "photoUrls": [
      "https://wannabechef.com/gorgonzola.jpg"
    ],
    "tags": [
      {
        "id": 1,
        "name": "blue"
      }
    ],
    "status": "available",
    "origin": "Italy",
    "pricePerKg": 28.5,
    "ageMonths": 12,
    "organic": false,
    "createdAt": "2024-01-15T09:30:00Z",
    "updatedAt": "2024-01-15T09:30:00Z"
  },
  "createdAt": "2024-01-15T09:30:00Z"
}

CustomerInput

object
usernamestringrequired
firstNamestring
lastNamestring
emailstring<email>required
passwordstring<password>required
phonestring | null
Example
{
  "username": "string",
  "firstName": "string",
  "lastName": "string",
  "email": "user@example.com",
  "password": "********",
  "phone": "string"
}

Error

object
codeinteger<int32>required
typestring
messagestringrequired
Example
{
  "code": 404,
  "type": "Not found",
  "message": "Your cheese has already been eaten"
}

ValidationError

object
codeinteger<int32>
typestring
messagestring
errorsArray<object>

Individual field validation errors

Show child attributes
fieldstring

The field that failed validation

messagestring

Human-readable error message

Example
{
  "code": 422,
  "type": "Validation error",
  "message": "Your cheese is not mouldy enough",
  "errors": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}
Built with Sourcey