Automattic / Automattic/jetpack-crm

API create endpoints echo the request payload instead of the persisted record

Open
#22 1 comment 0 reactions 0 assignees View on GitHub
enhancement ready-for-agent
Dominant language
PHP
Stars
13
Forks
8
Avg merge
1d 10h
Merged PRs (30d)
13

Description

> *This was generated by AI during triage.*

Split out of #21, where this behaviour is why a silent data-loss bug went unnoticed.

## Problem

The legacy `api/` create endpoints answer a successful write by echoing back the caller's submitted fields, plus an `id` if a new record was created. They do not report what was actually persisted.

This affects `create_customer`, `create_company`, `create_transaction` and `create_event` — each assembles its response from the request payload rather than re-reading the saved object.

The response is therefore not evidence that anything was stored. Any field that is dropped, coerced, truncated, or overridden between the request and the database is still reflected back to the caller verbatim, with a `200`. A caller has no way to tell a successful write from a partially discarded one without issuing a second read request.

#21 is a concrete instance: a date custom field is silently stripped before it reaches the DAL, and the create response still echoes the submitted date. The reporter of that issue explicitly called the response misleading. That specific bug is being fixed on its own; this issue is about the response contract that hid it.

Other cases the current shape can hide, independent of #21:

- Server-side defaults applied on create (e.g. a status falling back to the configured default) are not visible to the caller.
- Autonumber custom fields generated during the write are not returned.
- Values normalised on save (dates converted to timestamps, numeric coercion, tag resolution) are echoed in their submitted form, not their stored form.
- A sticky-status rule that deliberately overrides the submitted status is invisible in the response.

## Suggested direction

Return the persisted record — re-read the object after the write and serialise that, so the response reflects the database rather than the request.

The obvious objection is that this is a breaking change to a public API. Integrations may be reading fields back out of these responses and would see different values (timestamps instead of date strings, overridden statuses, populated autonumbers) — which is the point, but it is still a behaviour change for existing callers. Options worth weighing during triage:

- Change the response outright and treat it as a breaking change in a major release.
- Add the persisted record alongside the echo under a new key, leaving existing keys untouched.
- Make it opt-in per request, so existing callers are unaffected.

Worth noting that the newer v4 REST controllers (`src/rest-api/v4/`) are the modern surface and are not affected by this; a decision here may reasonably be "leave the legacy API alone and direct integrations to v4 instead", which is a legitimate outcome.

## Notes for triage

Leaning bug rather than enhancement — a success response that reports unpersisted values is wrong, not merely missing a feature — but the fix is an API contract change, so the category is genuinely arguable and the release-timing question matters more than the label.

Not blocking #21. That fix stands on its own.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in the legacy api/ create_customer, create_company, create_transaction, and create_event entry points and trace how each builds its successful response. Review the contract options in this issue and the related behavior in #21 before choosing whether to change, extend, or leave the legacy response unchanged. Done means the selected contract is implemented consistently and its persisted-versus-request behavior is covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
api, backend
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.