Why it’s risky to sync property management requests one way
In PDP Mobile, we implemented two-way synchronization of service requests with the property management company’s CRM: 12 statuses, a service tree, and a mock mode for the external API. Here’s where an integration stops being just a form submission.

“Why do we need two-way synchronization if a request can just be sent to the CRM once?”
Fair question. Especially when, in a mobile app, a request looks like a form: service, address, comment, submit. It seems like everything after that lives in the property management company’s CRM, and the app can forget about the record.
Our controversial takeaway after the PDP Mobile task: for service requests, one-way synchronization is often worse than no integration at all. The user sees a button in the app and assumes the app knows what happened to the request. If the status changes in the CRM but the mobile client still shows “new,” trust breaks faster than the integration can deliver value.
A request is not a message into the void
In PDP Mobile, we synchronized service requests with the property management company’s CRM in both directions. Over the lifecycle, there were 12 statuses: from a new request to accepted, in progress, completed, postponed, closed, and variants in between.
The main challenge here is not the number of statuses itself. Twelve values can go into an enum and you can move on. The problem is that the status changes in more than one place.
A resident creates a request in the mobile app. After that, the property management company handles it in its CRM. There it gets accepted, moved to work, postponed, and closed. The mobile app has to see those changes and show them to the user. At the same time, there may also be actions in the app that need to be sent back to the CRM.
During the discussion, an uncomfortable question came up quickly: who owns the status? If you say “the CRM is always the source of truth,” the app turns into a display layer and loses part of the workflow. If you treat the app as an equal source, you need to carefully agree on which status transitions are allowed from each side.
And that’s where one-way submission stops looking simple. It saves integration effort at the start, but creates a gray area: the record was supposedly sent, but what happens next is unknown.
A service tree can’t be replaced with a string
The second part of the task was the service catalog. It is hierarchical: for example, “Plumbing → Faucet replacement → Faucet with installation.”
We could have sent the selected service to the CRM as a plain string. That would have been faster to implement, but then the questions start:
- how does the CRM know the service belongs to plumbing;
- what if the name changes;
- how do you distinguish similar services in different branches;
- how do you build analytics by category if the structure is lost in transit.
That’s why, for an integration, it’s not just the request as an object that matters, but also the context of the selected service. The service tree affects routing, processing, and reporting inside the property management company. If the mobile app sends only the final name, it strips out information the CRM needs.
A real detail: at this point, it was tempting to simplify the model into a flat list. In the UI, the user still sees the final service. But integration reads the data differently: it needs to preserve the selection path, or part of the meaning is lost at the boundary between systems.
Mock mode is not just decoration for tests
The external CRM in the project had a mock mode for testing. For this kind of integration, that turned out to be more important than it sounds in the first meeting.
When you have 12 statuses and two-way exchange, development should not stop because the external API is unavailable. You need to verify transitions, response handling, and the behavior of both the app and the backend without waiting for a live CRM.
Mock mode helps you run through scenarios: a new request goes out, the CRM returns acceptance, then “in progress,” then “completed” or “postponed.” You don’t have to ask the external system to create the required state manually every time. And you don’t have to guess whether the bug is on our side or whether the API is currently returning something unexpected.
There is a tradeoff here. Mocking does not prove that the integration is fully ready for the real CRM. It proves that our side can work according to the agreed contract. A final check against the external API is still necessary.
Where we might be wrong
Two-way synchronization is not always justified. If the CRM is used only as an archive of requests, and the user does not expect statuses in the app, one-way submission may be enough. If the lifecycle has only two states and does not affect the client flow, full synchronization will just add unnecessary overhead.
But with service requests, that is rarely the case. The user submits a request not for the sake of submission itself. They want to know whether it was accepted, whether it was taken into work, why it was postponed, and when it was closed.
That’s why in PDP Mobile we went with two-way exchange: the request lives between the mobile app and the property management company’s CRM, statuses go through the full lifecycle, the service catalog is transferred with its hierarchy, and development does not depend on the external API being available thanks to mock mode. The next layer of this kind of integration is no longer just “send the request,” but agreeing on transition rules and sources of truth for each status.