Search code examples
acumaticafilemaker

Get Contact(s) in Acumatica via RESTful API


@HB_ACUMATICA, et al,

I've been working on integrating a client's FileMaker database with Acumatica for the past few months. I'm able to access (get/put) various tables (entities), such as PROJECT and CUSTOMER, but the CONTACT entity always produces an error. For example,

https://mydomain.acumatica.com/entity/Default/18.200.001/Customer [works fine]

https://mydomain.acumatica.com/entity/Default/18.200.001/Contact [always an error 500]

**[EDIT: The above examples are, of course, incomplete, unless trying to find 'all' Contact records. In testing, I was specifying actual Contact IDs, as in,

https://mydomain.acumatica.com/entity/Default/18.200.001/Customer/Nobody

where 'Nobody' is a real Contact ID... or so I was led to believe... see my answer below]**

Everywhere I have looked in the documentation, it indicates "Contact" is the proper name for the Entity. What am I doing wrong?

Much thanks. -- Erik


Solution

  • It is a known issue that hasn't been fixed yet. The error message returned by the web service call is:

    {
        "message": "An error has occurred.",
        "exceptionMessage": "Optimization cannot be performed.The following fields cause the error:\r\nAddressValidated: View AddressCurrent has BQL delegate\r\n",
        "exceptionType": "PX.Api.ContractBased.OptimizedExport.CannotOptimizeException",
        "stackTrace": "   at PX.Api.ContractBased.OptimizedExport.NotWorkingOptimizedExportProvider.get_CanOptimize() in C:\\Bld2\\AC-FULL2017R21-JOB1\\sources\\NetTools\\PX.Api.ContractBased\\OptimizedExport\\NotWorkingOptimizedExportProvider.cs:line 84\r\n   at PX.Api.ContractBased.EntityService.GetList(ISystemContract systemContract, String version, String name, EntityImpl entity, Boolean returnFullEntities, CbOperationContext operationContext, Boolean ignoreValueFields, PXGraph graph) in C:\\Bld2\\AC-FULL2017R21-JOB1\\sources\\NetTools\\PX.Api.ContractBased\\EntityService.cs:line 116\r\n   at PX.Api.ContractBased.Soap.SoapFacadeBase.GetListImpl(Entity entity, Boolean returnFullEntities) in C:\\Bld2\\AC-FULL2017R21-JOB1\\sources\\NetTools\\PX.Api.ContractBased\\Soap\\SoapFacadeBase.cs:line 83\r\n   at PX.Api.ContractBased.SystemContracts.V2.RestController.GetList(String objectName, String select, String filter, String expand, String custom, Nullable`1 skip, Nullable`1 top) in C:\\Bld2\\AC-FULL2017R21-JOB1\\sources\\NetTools\\PX.Api.ContractBased\\SystemContracts\\V2\\RestController.cs:line 247\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
    }
    

    The error occurs when fetching field AddressValidated. However that field isn't even returned by the request. EDIT it is returned only when the Address Validation feature is activated

    As a workaround what I did is fetch a single contact by ContactID and then copy all the field name returned. I then put those fields in the select clause of the request which specifies which field should be returned. This appears to have the side effect of not involving AddressValidated and the call succeeded:

    https://mydomain.acumatica.com/entity/Default/18.200.001/?$select=Active,AddressIsSameAsInAccount,BusinessAccount,CompanyName,ContactClass,ContactID,ContactMethod,ConvertedBy,DateOfBirth,DisplayName,DoNotCall,DoNotEmail,DoNotFax,DoNotMail,Duplicate,DuplicateFound,Email,Fax,FaxType,FirstName,Gender,Image,JobTitle,LanguageOrLocale,LastIncomingActivity,LastName,LastOutgoingActivity,MaritalStatus,MiddleName,NoMarketing,NoMassMail,Owner,OwnerEmployeeName,ParentAccount,Phone1,Phone1Type,Phone2,Phone2Type,Phone3,Phone3Type,QualificationDate,Reason,Source,SourceCampaign,SpouseOrPartnerName,Status,Synchronize,Title,Type,WebSite,Workgroup,WorkgroupDescription
    

    As Samvel Petrosov mentioned you can also extend the endpoint and remove the AddressValidated field from there (this doesn't seem to apply for fields coming from default endpoint, only use for customized fields): enter image description here

    With that approach you would have to change the endpoint in the URL to the extended endpoint name ('DefaultPlus' in this example):

    https://mydomain.acumatica.com/entity/DefaultPlus/18.200.001/Contact