Migrating to v4¶
What changed in v4¶
The HTTP verb sent by every diary-mutation method changed. v3 sent
DELETE and PUT to FatSecret’s method-style endpoint
(/rest/server.api?method=...); v4 sends POST to the same
endpoint. The wire-level params and the FatSecret-side semantics are
unchanged — only the HTTP verb is different.
Why the change¶
FatSecret’s REST API exposes most endpoints two ways:
A modern path-based URL (
/rest/food-entries/v1) with a conventional HTTP verb (DELETEfor delete,PUTfor edit).A legacy method-param URL (
/rest/server.api?method=...) that acceptsGET(reads) andPOST(writes), and rejects ``DELETE``/``PUT`` with HTTP 404.
The auto-generated OAS scraper picked up the DELETE/PUT verb
that FatSecret’s docs document for the path-based URL form, but the
generated client was routing all calls through the legacy method-param
URL. Result: every DELETE and PUT call in v3 silently failed
with 404, regardless of the operation succeeding semantically.
v4 maps DELETE/PUT down to POST for method-style
endpoints. GET (reads) and POST (writes that already used POST
in v3) are unchanged. The path-based native APIs (image recognition,
NLP, feedback) are not affected — they already use the correct REST
verbs against the modern URL.
Affected methods¶
All previously sent DELETE or PUT to the legacy URL and
silently 404’d. v4 sends POST:
fs.diary.entry_delete_v1fs.diary.entry_edit_v1fs.recipes.delete_favorite_v1(also affected; hand-written wrapper updated)fs.profile_foods.delete_v1,fs.profile_foods.delete_favorite_v1,fs.profile_foods.edit_v1fs.meals.delete_v1,fs.meals.edit_v1,fs.meal_items.delete_v1,fs.meal_items.edit_v1fs.exercises.entries_update_v1
The actual server-side semantics for each call are unchanged; only the HTTP verb the client sends differs.
Migration steps¶
Production code that calls these methods: no changes needed. The Python API surface (
fs.diary.entry_delete_v1(food_entry_id=...)) is identical. The only difference is what HTTP verb hits FatSecret, and v4’s verb is the one the server actually accepts.A side-effect worth knowing: if you had v3 in production and your classifier-delete or entry-edit logic appeared to “almost work” — reads returned current state, but mutations seemed to be intermittently missed — v4 will start actually applying those mutations. Audit any consumer that built a workaround for the silent-fail behavior (e.g. duplicate-detection on re-read, or diary cleanup scripts that delete-by-iteration). Those workarounds become unnecessary; some may now over-fire.
Test mocks that asserted the v3 verb: update assertions from
DELETE/PUTtoPOST:# v3 assert mock_call.call_args.kwargs["method"] == "DELETE" # v4 assert mock_call.call_args.kwargs["method"] == "POST"
This is the only test-suite-level change required.
Local downstream workarounds: if you implemented a workaround like
fs._call({"method": "food_entry.delete", ...}, method="GET")(because the v3 wrapper was 404-ing), you can drop the workaround and callfs.diary.entry_delete_v1(food_entry_id=...)directly.
Verification¶
The lib’s unit-test suite asserts the new verbs against fresh mocks;
running make test after pinning to fatsecret>=4.0.0 is
sufficient to verify your downstream test mocks are updated.
To verify against live FatSecret:
from fatsecret import Fatsecret
fs = Fatsecret(...)
# Create a throwaway entry then delete it; v3 would 404 silently,
# v4 returns FatSecret's success envelope.
fs.diary.entry_create_v1(food_id=..., ...)
entries = [e.to_dict() for e in fs.diary.entries_get_v2(...)]
entry_id = entries[-1]["food_entry_id"]
result = fs.diary.entry_delete_v1(food_entry_id=entry_id)
# v3: silently returned None even though server returned 404
# v4: returns True (success) or raises on real failure
No model/shape changes¶
Unlike v3 — which introduced Pydantic v2 models on the namespaced
surface — v4 changes only the HTTP transport. All return types,
constructor signatures, and method names are identical. .to_dict()
still works, attribute access still works, model_validate still
works. If your v3 code passes tests today and doesn’t rely on the
broken v3 mutation behavior, it will run on v4 unmodified.