Émile Bottles API
The Bottles API from Émile — 4 operation(s) for bottles.
The Bottles API from Émile — 4 operation(s) for bottles.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/emile-wine:emile-wine-bottles-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Émile Bottles API
description: '# Émile API
Public API for the Émile wine cellar app.
## Authentication
Two methods are supported:
**1. API Key** (recommended for external clients: MCP servers, scripts, ChatGPT custom connectors)
Send your key in the `X-API-Key` header OR as `Authorization: Bearer emile_live_...`.
Generate keys from your iOS app: **Profil → Paramètres → Clés API**.
**2. Supabase JWT** (used by the official iOS app — internal)
Send `Authorization: Bearer `.
## Rate Limits
All endpoints are rate-limited per user. See each endpoint''s documentation for specific limits.
On exceeded: HTTP 429 with `Retry-After` header and `X-RateLimit-*` informational headers.
| Endpoint | Limit |
|---|---|
| `POST /scan` | 10/min, 50/day |
| `POST /me/scan:batch` | 5/hour |
| `POST /recommendations` | 20/min, 100/day |
| `POST /cellars/{id}/bottles` | 60/min, 500/day |
| `POST /me/bottles:batch` | 10/hour, 50/day |
| `POST /me/keys` | 5/hour, 20/day |'
version: '1.0'
tags:
- name: Bottles
paths:
/me/bottles:batch:
post:
tags:
- Bottles
summary: Batch-create bottles (text mode)
description: 'Creates up to 100 bottles in one call. Each bottle is processed
independently — partial success is supported.
**Rate limit**: 10/hour, 50/day.
**Returns**: per-bottle status. Each entry is `{"status": "created", "id": "..."}` or
`{"status": "error", "error": "..."}`. Aggregate counts in `created` and `errored`.'
operationId: batch_create_bottles_me_bottles_batch_post
security:
- HTTPBearer: []
parameters:
- name: X-API-Key
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Api-Key
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BatchBottlesRequest'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
type: object
additionalProperties: true
title: Response Batch Create Bottles Me Bottles Batch Post
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/cellars/{cellar_id}/bottles:
get:
tags:
- Bottles
summary: List Bottles
operationId: list_bottles_cellars__cellar_id__bottles_get
security:
- HTTPBearer: []
parameters:
- name: cellar_id
in: path
required: true
schema:
type: string
title: Cellar Id
- name: X-API-Key
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Api-Key
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
post:
tags:
- Bottles
summary: Add Bottle
description: 'Create individual bottle rows. quantity=N creates N rows (1 per physical bottle).
Returns a list of created bottles.'
operationId: add_bottle_cellars__cellar_id__bottles_post
security:
- HTTPBearer: []
parameters:
- name: cellar_id
in: path
required: true
schema:
type: string
title: Cellar Id
- name: X-API-Key
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Api-Key
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BottleCreate'
responses:
'201':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/cellars/{cellar_id}/bottles/{bottle_id}:
patch:
tags:
- Bottles
summary: Update Bottle
operationId: update_bottle_cellars__cellar_id__bottles__bottle_id__patch
security:
- HTTPBearer: []
parameters:
- name: cellar_id
in: path
required: true
schema:
type: string
title: Cellar Id
- name: bottle_id
in: path
required: true
schema:
type: string
title: Bottle Id
- name: X-API-Key
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Api-Key
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BottleUpdate'
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
delete:
tags:
- Bottles
summary: Delete Bottle
operationId: delete_bottle_cellars__cellar_id__bottles__bottle_id__delete
security:
- HTTPBearer: []
parameters:
- name: cellar_id
in: path
required: true
schema:
type: string
title: Cellar Id
- name: bottle_id
in: path
required: true
schema:
type: string
title: Bottle Id
- name: X-API-Key
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Api-Key
responses:
'204':
description: Successful Response
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/cellars/{cellar_id}/bottles/{bottle_id}/photo:
post:
tags:
- Bottles
summary: Upload Location Photo
description: 'Upload a photo of the bottle''s physical location in the cellar.
Stores the image in Supabase Storage and updates location_photo_url on the bottle.
Max file size: 10 MB.'
operationId: upload_location_photo_cellars__cellar_id__bottles__bottle_id__photo_post
security:
- HTTPBearer: []
parameters:
- name: cellar_id
in: path
required: true
schema:
type: string
title: Cellar Id
- name: bottle_id
in: path
required: true
schema:
type: string
title: Bottle Id
- name: X-API-Key
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Api-Key
requestBody:
required: true
content:
multipart/form-data:
schema:
$ref: '#/components/schemas/Body_upload_location_photo_cellars__cellar_id__bottles__bottle_id__photo_post'
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
components:
schemas:
ValidationError:
properties:
loc:
items:
anyOf:
- type: string
- type: integer
type: array
title: Location
msg:
type: string
title: Message
type:
type: string
title: Error Type
input:
title: Input
ctx:
type: object
title: Context
type: object
required:
- loc
- msg
- type
title: ValidationError
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
BatchBottlesRequest:
properties:
bottles:
items:
$ref: '#/components/schemas/BottleSpec'
type: array
maxItems: 100
minItems: 1
title: Bottles
type: object
required:
- bottles
title: BatchBottlesRequest
BottleSpec:
properties:
cellar_id:
type: string
format: uuid
title: Cellar Id
wine_reference_id:
anyOf:
- type: string
- type: 'null'
title: Wine Reference Id
vintage:
anyOf:
- type: integer
maximum: 2100.0
minimum: 1900.0
- type: 'null'
title: Vintage
quantity:
type: integer
maximum: 100.0
minimum: 1.0
title: Quantity
default: 1
location_text:
anyOf:
- type: string
- type: 'null'
title: Location Text
location_photo_url:
anyOf:
- type: string
- type: 'null'
title: Location Photo Url
purchase_price:
anyOf:
- type: number
minimum: 0.0
- type: 'null'
title: Purchase Price
notes:
anyOf:
- type: string
- type: 'null'
title: Notes
type: object
required:
- cellar_id
title: BottleSpec
BottleUpdate:
properties:
status:
anyOf:
- type: string
- type: 'null'
title: Status
location_text:
anyOf:
- type: string
- type: 'null'
title: Location Text
notes:
anyOf:
- type: string
- type: 'null'
title: Notes
purchase_price:
anyOf:
- type: number
- type: 'null'
title: Purchase Price
cellar_id:
anyOf:
- type: string
- type: 'null'
title: Cellar Id
type: object
title: BottleUpdate
Body_upload_location_photo_cellars__cellar_id__bottles__bottle_id__photo_post:
properties:
file:
type: string
contentMediaType: application/octet-stream
title: File
type: object
required:
- file
title: Body_upload_location_photo_cellars__cellar_id__bottles__bottle_id__photo_post
BottleCreate:
properties:
wine_reference_id:
anyOf:
- type: string
- type: 'null'
title: Wine Reference Id
vintage:
anyOf:
- type: integer
- type: 'null'
title: Vintage
quantity:
type: integer
maximum: 100.0
minimum: 1.0
title: Quantity
default: 1
location_text:
anyOf:
- type: string
- type: 'null'
title: Location Text
location_photo_url:
anyOf:
- type: string
- type: 'null'
title: Location Photo Url
purchase_price:
anyOf:
- type: number
- type: 'null'
title: Purchase Price
notes:
anyOf:
- type: string
- type: 'null'
title: Notes
type: object
title: BottleCreate
securitySchemes:
HTTPBearer:
type: http
scheme: bearer