Impacted plugin
Jetpack
Quick summary
Contact date custom fields are not saved when creating/updating a contact via the CRM REST/API create_customer endpoint, even when a valid Y-m-d value is sent and the API response looks successful.
Root cause: the date is converted to a Unix timestamp once in api/create_customer.php, then converted again inside zeroBS_addUpdateCustomer() → zeroBS_buildContactMeta(). The second pass expects Y-m-d, receives a timestamp string, fails parsing (false), and removeEmpties=true strips the field before save.
Steps to reproduce
In Jetpack CRM → Settings → Custom Fields, create a Contact custom field of type Date (example label: Contract Date, slug e.g. contract-date).
Enable the CRM API and note the API key/secret.
POST to the create/update customer API endpoint with JSON similar to:
{
"email": "apitest-date-cf@example.com",
"fname": "API",
"lname": "DateTest",
"status": "Customer",
"contract-date": "2026-07-23"
}
Confirm the API response returns success / echoes the payload (including the date).
Open the contact in CRM admin, or fetch via the customers API (withCustomFields is enabled there), or query wp_zbs_customfields for the contact.
Expected
contract-date is stored as a Unix timestamp (UTS) and shown as 2026-07-23 in the contact UI / API read responses.
Actual
The contact is created/updated, but the date custom field is missing/empty. The create endpoint response is misleading because it returns the request payload, not the persisted custom-field state.
Technical root cause
Pass 1 — api/create_customer.php
$customer_array = zeroBS_buildContactMeta( $new_customer, array(), '', 'zbsc_', $remove_empties, $autogen_autonumbers );
Input key: contract-date = "2026-07-23"
Date branch in zeroBS_buildObjArr():
case 'date':
$retArray[ $outputPrefix . $fK ] = jpcrm_date_str_to_uts( $safe_text, '!Y-m-d', true );
Result: zbsc_contract-date = e.g. 1784764800 (int UTS)
Pass 2 — zeroBS_addUpdateCustomer() in includes/ZeroBSCRM.DAL3.Helpers.php
$zbsCustomerMeta = zeroBS_buildContactMeta( $cFields, $existingMeta, $metaBuilderPrefix, '', true );
Re-reads zbsc_contract-date (already UTS)
Date branch again runs jpcrm_date_str_to_uts( '1784764800', '!Y-m-d', true )
DateTime::createFromFormat( '!Y-m-d', '1784764800' ) fails → false
With $removeEmpties = true, empty(false) removes the key
addUpdateContact() never receives the custom field value
Same pattern exists for companies (api/create_company.php + zeroBS_addUpdateCompany / shared zeroBS_buildObjArr date handling).
Site owner impact
More than 60% of the total website/platform users
Severity
Critical
What other impact(s) does this issue have?
Platform revenue
If a workaround is available, please outline it here.
Suggested fix
One of:
Skip re-normalization for already-parsed UTS in the date case of zeroBS_buildObjArr():
case 'date':
$raw = $arraySource[ $fieldPrefix . $fK ];
if ( is_numeric( $raw ) ) {
$retArray[ $outputPrefix . $fK ] = (int) $raw;
break;
}
$safe_text = sanitize_text_field( $raw );
$retArray[ $outputPrefix . $fK ] = jpcrm_date_str_to_uts( $safe_text, '!Y-m-d', true );
break;
Or stop calling zeroBS_buildContactMeta twice in the API → zeroBS_addUpdateCustomer path (pass already-built meta through, or only sanitize once).
Add a regression test: API create contact with a date custom field, assert custom field row exists with expected UTS.
Platform (Simple and/or Atomic)
Self-hosted
Impacted plugin
Jetpack
Quick summary
Contact date custom fields are not saved when creating/updating a contact via the CRM REST/API create_customer endpoint, even when a valid Y-m-d value is sent and the API response looks successful.
Root cause: the date is converted to a Unix timestamp once in api/create_customer.php, then converted again inside zeroBS_addUpdateCustomer() → zeroBS_buildContactMeta(). The second pass expects Y-m-d, receives a timestamp string, fails parsing (false), and removeEmpties=true strips the field before save.
Steps to reproduce
In Jetpack CRM → Settings → Custom Fields, create a Contact custom field of type Date (example label: Contract Date, slug e.g. contract-date).
Enable the CRM API and note the API key/secret.
POST to the create/update customer API endpoint with JSON similar to:
{
"email": "apitest-date-cf@example.com",
"fname": "API",
"lname": "DateTest",
"status": "Customer",
"contract-date": "2026-07-23"
}
Confirm the API response returns success / echoes the payload (including the date).
Open the contact in CRM admin, or fetch via the customers API (withCustomFields is enabled there), or query wp_zbs_customfields for the contact.
Expected
contract-date is stored as a Unix timestamp (UTS) and shown as 2026-07-23 in the contact UI / API read responses.
Actual
The contact is created/updated, but the date custom field is missing/empty. The create endpoint response is misleading because it returns the request payload, not the persisted custom-field state.
Technical root cause
Pass 1 — api/create_customer.php
$customer_array = zeroBS_buildContactMeta( $new_customer, array(), '', 'zbsc_', $remove_empties, $autogen_autonumbers );
Input key: contract-date = "2026-07-23"
Date branch in zeroBS_buildObjArr():
case 'date':
$retArray[ $outputPrefix . $fK ] = jpcrm_date_str_to_uts( $safe_text, '!Y-m-d', true );
Result: zbsc_contract-date = e.g. 1784764800 (int UTS)
Pass 2 — zeroBS_addUpdateCustomer() in includes/ZeroBSCRM.DAL3.Helpers.php
$zbsCustomerMeta = zeroBS_buildContactMeta( $cFields, $existingMeta, $metaBuilderPrefix, '', true );
Re-reads zbsc_contract-date (already UTS)
Date branch again runs jpcrm_date_str_to_uts( '1784764800', '!Y-m-d', true )
DateTime::createFromFormat( '!Y-m-d', '1784764800' ) fails → false
With $removeEmpties = true, empty(false) removes the key
addUpdateContact() never receives the custom field value
Same pattern exists for companies (api/create_company.php + zeroBS_addUpdateCompany / shared zeroBS_buildObjArr date handling).
Site owner impact
More than 60% of the total website/platform users
Severity
Critical
What other impact(s) does this issue have?
Platform revenue
If a workaround is available, please outline it here.
Suggested fix
One of:
Skip re-normalization for already-parsed UTS in the date case of zeroBS_buildObjArr():
case 'date':
$raw = $arraySource[ $fieldPrefix . $fK ];
if ( is_numeric( $raw ) ) {
$retArray[ $outputPrefix . $fK ] = (int) $raw;
break;
}
$safe_text = sanitize_text_field( $raw );
$retArray[ $outputPrefix . $fK ] = jpcrm_date_str_to_uts( $safe_text, '!Y-m-d', true );
break;
Or stop calling zeroBS_buildContactMeta twice in the API → zeroBS_addUpdateCustomer path (pass already-built meta through, or only sanitize once).
Add a regression test: API create contact with a date custom field, assert custom field row exists with expected UTS.
Platform (Simple and/or Atomic)
Self-hosted