Trouble setting locations to closed on all days

I’m using the JavaScript updateLocation api to maintain open hours. This allows store managers to modify/close stores in the case of power outages etc.

I’m having trouble when the manager needs to close the store completely (a food truck in winter, a power outage occurs).

If I send an empty array of businessHours, I get a nice error, which seems to want to clarify what I’m supposed to do to close the store completely (pass null):

But I can’t get it to work. Here’s what I initially guessed to do (empty array of days):

const payload = {
	location: {
		businessHours: []
	}
}
const updateResponse = await API.locations.updateLocation("ABCDEFGHIJ", payload)

This throws an error, and the response message is trying to be helpful: "Unspecified business hour periods. Clear business hours by setting the top-level field to null."

It’s unclear what “top-level field” is referring to, but I’m taking a guess it means businessHours(?)

So I send this instead:

const payload = {
	location: {
		businessHours: null
	}
}
const updateResponse = await API.locations.updateLocation("ABCDEFGHIJ", payload)

Response is now: "Given value: null\nType: 'object'\nExpected type: 'Optional<Lazy<Object<{periods}>>>'\nPath: location › businessHours"

I’m just not sure which field I’m supposed to set to null to clear business hours. I feel like I’m close but just missing some small detail. Any ideas?

Are you including the X-Clear-Null in the header and setting it to true? If you want to set an existing field value to null , you must include the X-Clear-Null header. Otherwise, the request succeeds but the value is not cleared. For example:

  curl -X PUT \
-H 'Authorization: Bearer {ACCESS_TOKEN}' \
-H "Content-type: application/json" \
-H 'X-Clear-Null: true'
-d '{
   "location":{
      "business_hours": null
   }
}' \
'https://connect.squareupsandbox.com/v2/locations/{location_id}'

:slightly_smiling_face:

1 Like

Thanks, Bryan. That’s good to know about. I’m actually using your Node.js SDK to make these calls (not building http requests from scratch). Is there a way to make this same setting using the Saure Node.js SDK?

You will need to add it to the client as an additional header that’s passed in on an UpdateLocation call. :slightly_smiling_face:

Thanks, Bryan!

If I make the call using curl as you did, it definitely works to set the header and set the location.businessHours to null. I can see that update in the square backend no problem.

I also figured out how to set the additionalHeaders in the node.js SDK, so thanks for the hint.

I still cannot make this work when using the Square node.js SDK. Complete repro code is below, and I think I see the problem:

– the Square node.js is typescript, and it’s enforcing that businessHours must be Optional<Lazy<Object<{periods}>>>
– before the node SDK sends the HTTP request, it checks the payload, sees the null I assigned, and throws a type mismatch exception
– while I did figure out how to set that extra header, it doesn’t matter since the square node.js SDK throws the exception before making the request.

I think this must be possible, but my lack of Typescript knowledge may be the blocker. I’m just at a loss how to assign null in my JS code when the expected data type is Optional<Lazy<Object<{periods}>>>. Any ideas?

Here’s a concise node.js SDK code example, and following is the exception thrown by the node.js SDK:

const config = {
	accessToken: "SQUARE_ACCESS_TOKEN",
	environment: "SQUARE_ENVIRONMENT",
	additionalHeaders: { 'X-Clear-Null': 'true' }
};
  
const square = new Client(config); 
const locationId = "SQUARE_LOCATION_ID"

try {
	var payload = {
	  location: {
	    businessHours: null
	  }
	}
	
	const updateResponse = await square.locationsApi.updateLocation(locationId, payload)

	return {
	  success: true,
	  message: "No exception thrown"
	}
	
} catch(error) {
	return {
	  success: false,
	  message: error.message
	};
}

Exception thrown (before HTTP request is attempted):

squareUpdateStoreHours Error: Argument for 'body' failed validation.
Expected value to be of type 'Optional<Lazy<Object<{periods}>>>' but found 'object'.

Given value: null
Type: 'object'\nExpected type: 'Optional<Lazy<Object<{periods}>>>'
Path: location › businessHours
    at new ArgumentsValidationError (/.../node_modules/@apimatic/core/lib/errors/argumentsValidationError.js:48:24)
        at DefaultRequestBuilder.prepareArgs (/.../node_modules/@apimatic/core/lib/http/validate.js:41:15)
            at LocationsApi._callee4$ (/.../node_modules/square/dist/square.cjs.development.js:11667:28)
                at tryCatch (/.../node_modules/square/dist/square.cjs.development.js:230:40)
                    at Generator.invoke [as _invoke] (/.../node_modules/square/dist/square.cjs.development.js:460:22)
                        at Generator.next (/.../node_modules/square/dist/square.cjs.development.js:285:21)
                            at asyncGeneratorStep (/.../node_modules/square/dist/square.cjs.development.js:13:24)
                                at _next (/.../node_modules/square/dist/square.cjs.development.js:35:9)
                                    at /.../node_modules/square/dist/square.cjs.development.js:42:7\n    at new Promise (<anonymous>)
                                        at LocationsApi.<anonymous> (/.../node_modules/square/dist/square.cjs.development.js:31:12)
                                            at LocationsApi.updateLocation (/.../node_modules/square/dist/square.cjs.development.js:11685:30)
                                                at /.../square/square-stores.js:536:54
                                                    at newHandler (/Users/robkerr/.nvm/versions/node/v16.20.0/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:317:16)
                                                        at fixedLen (/.../node_modules/firebase-functions/lib/v1/providers/https.js:74:41)
                                                            at /.../node_modules/firebase-functions/lib/common/providers/https.js:438:32 {
                                                            	  errors: { body: [ [Object] ] }
                                                            	  }"

@robkerr Based on the error messages and the information provided, it seems that there might be some confusion regarding the correct syntax to clear the business hours using the JavaScript updateLocation API. Here’s a suggestion to try:

javascriptCopy code

const payload = {
  location: {
    businessHours: {
      periods: null
    }
  }
};

const updateResponse = await API.locations.updateLocation("ABCDEFGHIJ", payload);

In this example, instead of setting businessHours directly to null, you can set it as an object with a periods field set to null. This structure aligns with the expected type mentioned in the error message (Optional<Lazy<Object<{periods}>>>'). By setting periods to null, you indicate that there are no business hour periods specified.

Please note that the exact syntax and structure may depend on the specific API you are using and its documentation. It’s always recommended to refer to the API documentation or reach out to the API provider for further clarification on how to properly clear the business hours.