[SalesForce] Integration with REST API that is not CRUD

I'm a developer working on an API that tries to be REST-ful, but is limited in terms of CRUD. Many entities expose a GET endpoint, but because many create and update actions have side-effects, we don't expose a simple CRUD interface and instead expose operations that can be performed. For example, a Member can be created and updated, but to cancel a Booking, you can't just update the status of the booking as that may have many side effects; instead you must call a cancel-booking endpoint.

However, we need to integrate with a Salesforce instance. I'm unfamiliar with Salesforce, but the developers I'm working with are expecting a CRUD interface, and have suggested using an OData adapter as data-source to talk to our API. I've got a few questions though, as this does not fit well with our API:

1) Does Salesforce support OData 'actions'? These seem a perfect fit for operations that have side effects beyond simple create/update

2) Is there an established best practice for integrating SalesForce with external API's that are REST-ful but not CRUD, or where the entities that can be read are not the same as those that can be created or updated

Best Answer

In Salesforce, everything is a CRUD operation. As far as your service is concerned, it needs to support CRUD OData operations. Your application would need to be modified to support CRUD operations. Databases typically support triggers, which is when some code is executed in response to a DML request. While salesforce does support using methods other than CRUD, you'll be left with the responsibility of writing your own Apex Code to support that logic.

If you wanted to translate standard CRUD operations into custom REST actions for OData, you could use the DataSource Connection class to implement custom Apex Code handlers, but this means you'll have to maintain your application and custom Apex Code. Simply rewriting your application to support proper CRUD operations would be more efficient than managing two sets of code just to have a common interface.

In your example, canceling a Booking should be as simple as calling POST /data/Booking('12345') with the post body { "@odata.type": "Booking", "Status": "Canceled" } (simplified for this example), with the result being that any business logic that needs to be executed (e.g. sending notifications, updating related records, etc) handled at the database level on the receiving end.

Related Topic