Platforms to show: All Mac Windows Linux Cross-Platform

/CURL/FMAPI/FileMaker Data API Test


Required plugins for this example: MBS CURL Plugin, MBS Main Plugin

Last modified Fri, 18th Sep 2025.

You find this example project in your MBS Xojo Plugin download as a Xojo project file within the examples folder: /CURL/FMAPI/FileMaker Data API Test

Download this example: FileMaker Data API Test.zip

Project "FileMaker Data API Test.xojo_binary_project"
Class App Inherits Application
Const kEditClear = "&Delete"
Const kFileQuit = "&Quit"
Const kFileQuitShortcut = ""
EventHandler Sub Open() Var l As New LoginWindow l.show End EventHandler
End Class
Class MainWindow Inherits Window
Control GetProductInfoButton Inherits PushButton
ControlInstance GetProductInfoButton Inherits PushButton
EventHandler Sub Action() response = connection.ProductInfo UpdateResponse // {"response":{"productInfo":{"name":"FileMaker Data API Engine","buildDate":"07/28/2020","version":"19.1.1.54","dateFormat":"MM/dd/yyyy","timeFormat":"HH:mm:ss","timeStampFormat":"MM/dd/yyyy HH:mm:ss"}},"messages":[{"code":"0","message":"OK"}]} If response.ErrorCode = 0 Then // show version number in dialog box Var result As Dictionary = response.Result Var productInfo As Dictionary = result.value("productInfo") If productInfo <> Nil Then Var version As String = productInfo.Value("version") MsgBox version End If End If End EventHandler
End Control
Control ResultTextArea Inherits TextArea
ControlInstance ResultTextArea Inherits TextArea
End Control
Control DebugTextArea Inherits TextArea
ControlInstance DebugTextArea Inherits TextArea
End Control
Control ResultField Inherits TextField
ControlInstance ResultField Inherits TextField
End Control
Control DatabaseNamesButton Inherits PushButton
ControlInstance DatabaseNamesButton Inherits PushButton
EventHandler Sub Action() response = connection.DatabaseNames UpdateResponse // {"response":{"databases":[{"name":"Contacts"}]},"messages":[{"code":"0","message":"OK"}]} If response.ErrorCode = 0 Then // show names of databases in dialog box Var result As Dictionary = response.Result Var Names() as string Var databases() As Variant = result.Value("databases") For Each entry As Dictionary In databases Var name As String = entry.Value("name") Names.Append name Next MsgBox "Database Names" + EndOfLine + EndOfLine + Join(names, EndOfLine) End If End EventHandler
End Control
Control LayoutNamesButton Inherits PushButton
ControlInstance LayoutNamesButton Inherits PushButton
EventHandler Sub Action() response = connection.LayoutNames UpdateResponse // {"response":{"layouts":[{"name":"Contacts","table":""},{"name":"Contacts Details","table":""}]},"messages":[{"code":"0","message":"OK"}]} If response.ErrorCode = 0 Then LayoutMenu.DeleteAllRows Var result As Dictionary = response.Result Var layouts() As Variant = result.Value("layouts") Var Names() As String WalkLayouts Layouts, Names 'MsgBox "Layout Names" + EndOfLine + EndOfLine + Join(names, EndOfLine) End If End EventHandler
End Control
Control ScriptNamesButton Inherits PushButton
ControlInstance ScriptNamesButton Inherits PushButton
EventHandler Sub Action() response = connection.ScriptNames UpdateResponse If response.ErrorCode = 0 Then ScriptMenu.DeleteAllRows Var result As Dictionary = response.Result Var scripts() As Variant = result.Value("scripts") Var Names() As String WalkScripts scripts, Names, "" 'MsgBox "Script Names" + EndOfLine + EndOfLine + Join(names, EndOfLine) End If End EventHandler
End Control
Control LayoutMenu Inherits PopupMenu
ControlInstance LayoutMenu Inherits PopupMenu
EventHandler Sub Change() UpdateButtons End EventHandler
End Control
Control LayoutMetadataButton Inherits PushButton
ControlInstance LayoutMetadataButton Inherits PushButton
EventHandler Sub Action() // which layout to use connection.Layout = LayoutMenu.Text response = connection.LayoutMetadata("") UpdateResponse // {"response":{"fieldMetaData":[{"name":"SomeText","type":"normal","displayType":"editText","result":"text","global":false,"autoEnter":false,"fourDigitYear":false,"maxRepeat":1,"maxCharacters":0,"notEmpty":false,"numeric":false,"timeOfDay":false,"repetitionStart":1,"repetitionEnd":1},... If response.ErrorCode = 0 Then Var result As Dictionary = response.Result Var fields() As Variant = result.value("fieldMetaData") Var Names() As String For Each entry As Dictionary In fields Var name As String = entry.Value("name") Names.Append name Next MsgBox "Field Names" + EndOfLine + EndOfLine + Join(names, EndOfLine) End If End EventHandler
End Control
Control GetRecordsButton Inherits PushButton
ControlInstance GetRecordsButton Inherits PushButton
EventHandler Sub Action() // which layout to use connection.Layout = LayoutMenu.Text Var request As New FMRequestMBS // doesn't work? 'request.sort = "[{""fieldName"":""SomeNumber"",""sortOrder"":""descent""}]" response = connection.GetRecords(request) UpdateResponse ShowRecords End EventHandler
End Control
Control RecordIDField Inherits TextField
ControlInstance RecordIDField Inherits TextField
EventHandler Sub TextChange() UpdateButtons End EventHandler
End Control
Control GetRecordButton Inherits PushButton
ControlInstance GetRecordButton Inherits PushButton
EventHandler Sub Action() // which layout to use connection.Layout = LayoutMenu.Text Var request As New FMRequestMBS request.sort = "SomeText" response = connection.GetRecord(request, RecordIDField.Text.Trim) UpdateResponse ShowRecords End EventHandler
End Control
Control ScriptMenu Inherits PopupMenu
ControlInstance ScriptMenu Inherits PopupMenu
EventHandler Sub Change() UpdateButtons End EventHandler
End Control
Control ExecuteScriptButton Inherits PushButton
ControlInstance ExecuteScriptButton Inherits PushButton
EventHandler Sub Action() connection.Layout = LayoutMenu.text Var scriptName As String = ScriptMenu.Text response = connection.ExecuteScript(scriptName, "TestParam") UpdateResponse End EventHandler
End Control
Control DuplicateRecordButton Inherits PushButton
ControlInstance DuplicateRecordButton Inherits PushButton
EventHandler Sub Action() // which layout to use connection.Layout = LayoutMenu.Text Var request As New FMRequestMBS response = connection.DuplicateRecord(request, RecordIDField.Text.Trim) UpdateResponse End EventHandler
End Control
Control SetGlobalFieldsButton Inherits PushButton
ControlInstance SetGlobalFieldsButton Inherits PushButton
EventHandler Sub Action() // which layout to use connection.Layout = LayoutMenu.Text Var request As New FMRequestMBS Var dic As New Dictionary Var now as new date // you may need to create such a field! dic.Value("Contacts::MyGlobalField") = "Hello World "+now.ShortTime response = connection.SetGlobalFields(dic) UpdateResponse End EventHandler
End Control
Control CreateRecordButton Inherits PushButton
ControlInstance CreateRecordButton Inherits PushButton
EventHandler Sub Action() // which layout to use connection.Layout = LayoutMenu.Text Var request As New FMRequestMBS Var fieldData as new Dictionary fieldData.Value("First Name") = "Joe" fieldData.Value("Last Name") = "Smith" fieldData.Value("Title") = "Mr." fieldData.Value("Company") = "Test Ltd." fieldData.Value("Website") = "https://www.mbsplugins.de/filemaker" request.fieldData = fieldData response = connection.CreateRecord(request) UpdateResponse End EventHandler
End Control
Control EditRecordButton Inherits PushButton
ControlInstance EditRecordButton Inherits PushButton
EventHandler Sub Action() // which layout to use connection.Layout = LayoutMenu.Text Var request As New FMRequestMBS Var fieldData as new Dictionary fieldData.Value("First Name") = "Bob" fieldData.Value("Last Name") = "Miller" request.fieldData = fieldData response = connection.EditRecord(request, RecordIDField.text.trim) UpdateResponse End EventHandler
End Control
Control UploadButton Inherits PushButton
ControlInstance UploadButton Inherits PushButton
EventHandler Sub Action() // which layout to use connection.Layout = LayoutMenu.Text Var request As New FMRequestMBS Var upload As New FMContainerUploadMBS upload.ContainerFieldName = "SomeContainer" upload.RecordId = RecordIDField.Text upload.ModId = ModIDField.Text.trim If Keyboard.AsyncShiftKey Then upload.DataString = "Hello World" upload.FileName = "Hello.txt" Else upload.SetPicture LogoMBS(500) upload.FileName = "image.png" End If response = connection.UploadToContainerField(upload) UpdateResponse End EventHandler
End Control
Control ModIDField Inherits TextField
ControlInstance ModIDField Inherits TextField
EventHandler Sub TextChange() UpdateButtons End EventHandler
End Control
Control DeleteRecordButton Inherits PushButton
ControlInstance DeleteRecordButton Inherits PushButton
EventHandler Sub Action() // which layout to use connection.Layout = LayoutMenu.Text Var request As New FMRequestMBS response = connection.DeleteRecord(request, RecordIDField.Text.Trim) UpdateResponse End EventHandler
End Control
Control FindRecordsButton Inherits PushButton
ControlInstance FindRecordsButton Inherits PushButton
EventHandler Sub Action() // which layout to use connection.Layout = LayoutMenu.Text // see // https://help.claris.com/en/data-api-guide/content/perform-find-request.html Var request As New FMRequestMBS // just query first 100 records request.offset = 1 request.limit = 100 // e.g. [{"Name" : "=Test"}] response = connection.FindRecords(request, queryField.Text.Trim) UpdateResponse ShowRecords End EventHandler
End Control
Control QueryField Inherits TextField
ControlInstance QueryField Inherits TextField
EventHandler Sub TextChange() UpdateButtons End EventHandler
End Control
Function FileClose() As Boolean close Return True End Function
Private Sub ShowRecords() If response.ErrorCode = 0 Then Var w As New RecordsWindow w.Setup response.Result End If End Sub
Sub UpdateButtons() Var HasLayout As Boolean = LayoutMenu.ListIndex >= 0 GetRecordsButton.Enabled = HasLayout LayoutMetadataButton.Enabled = HasLayout RecordIDField.Enabled = HasLayout SetGlobalFieldsButton.Enabled = HasLayout CreateRecordButton.Enabled = HasLayout Var HasRecordID As Boolean = RecordIDField.Text.Len > 0 GetRecordButton.Enabled = HasLayout And HasRecordID DuplicateRecordButton.Enabled = HasLayout And HasRecordID EditRecordButton.Enabled = HasLayout And HasRecordID Var HasScript As Boolean = ScriptMenu.ListIndex >= 0 ExecuteScriptButton.Enabled = HasScript And HasLayout Var HasModID As Boolean = ModIDField.Text.Len > 0 UploadButton.Enabled = HasLayout And HasRecordID And HasModID DeleteRecordButton.Enabled = HasLayout And HasRecordID FindRecordsButton.Enabled = HasLayout End Sub
Sub UpdateResponse() If response = Nil Then ResultField.Text = "No response!" DebugTextArea.Text = "" ResultTextArea.Text = "" Else ResultField.Text = Str(response.ErrorCode)+" "+response.ErrorMessage Var Debug As String = response.DebugMessages If response.ErrorCode <> 0 Then Debug = Debug + EndOfLine + EndOfLine + response.RawResultJSON End If DebugTextArea.Text = ReplaceLineEndings(Debug, EndOfLine) ResultTextArea.Text = ReplaceLineEndings(response.ResultJSON, EndOfLine) End If End Sub
Private Sub WalkLayouts(layouts() as Variant, names() as string) For Each entry As Dictionary In layouts Var name As String = entry.Value("name") Var isFolder As Boolean = entry.Lookup("isFolder", False) If isFolder Then // look one level deep Var folderLayoutNames() As Variant = entry.Value("folderLayoutNames") WalkLayouts folderLayoutNames, Names Else Names.Append name LayoutMenu.AddRow name End If Next End Sub
Private Sub WalkScripts(scripts() as Variant, Names() as string, Prefix as string) For Each entry As Dictionary In scripts Var name As String = entry.Value("name") Var isFolder As Boolean = entry.Lookup("isFolder", False) If isFolder Then // look one level deep Var NewScripts() As Variant = entry.Value("folderScriptNames") WalkScripts NewScripts, Names, Prefix + name + " > " Else Names.Append name ScriptMenu.AddRow name End If Next End Sub
Property connection As FMDataMBS
Property response As FMResponseMBS
End Class
MenuBar MainMenuBar
MenuItem FileMenu = "&File"
MenuItem FileClose = "Close"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem EditMenu = "&Edit"
MenuItem EditUndo = "&Undo"
MenuItem EditSeparator1 = "-"
MenuItem EditCut = "Cu&t"
MenuItem EditCopy = "&Copy"
MenuItem EditPaste = "&Paste"
MenuItem EditClear = "#App.kEditClear"
MenuItem EditSeparator2 = "-"
MenuItem EditSelectAll = "Select &All"
End MenuBar
Class LoginWindow Inherits Window
Control ServerField Inherits TextField
ControlInstance ServerField Inherits TextField
End Control
Control Label1 Inherits Label
ControlInstance Label1 Inherits Label
End Control
Control UserNameField Inherits TextField
ControlInstance UserNameField Inherits TextField
End Control
Control Label2 Inherits Label
ControlInstance Label2 Inherits Label
End Control
Control PasswordField Inherits TextField
ControlInstance PasswordField Inherits TextField
End Control
Control Label3 Inherits Label
ControlInstance Label3 Inherits Label
End Control
Control DatabaseNameField Inherits TextField
ControlInstance DatabaseNameField Inherits TextField
End Control
Control Label4 Inherits Label
ControlInstance Label4 Inherits Label
End Control
Control LoginButton Inherits PushButton
ControlInstance LoginButton Inherits PushButton
EventHandler Sub Action() // new connection to FileMaker Server Var d As New FMDataMBS 'd.Version = "v2" // default is vLatest d.Database = DatabaseNameField.Text.Trim d.Password = PasswordField.Text.Trim d.Username = UserNameField.Text.Trim d.Server = ServerField.Text.trim Var r As FMResponseMBS = d.Login If r = Nil Then Break Return End If // connection worked? If r.CURLErrorCode <> 0 Then ShowLog r MsgBox r.CURLErrorMessage Return End If Select Case r.ResponseCode Case 200 Var m As New MainWindow m.connection = d m.response = r m.UpdateResponse Self.close Case 401 ShowLog r MsgBox "Invalid credentials." else ShowLog r MsgBox "ResponseCode: "+Str(r.ResponseCode) End Select End EventHandler
End Control
Control CancelButton Inherits PushButton
ControlInstance CancelButton Inherits PushButton
EventHandler Sub Action() Quit End EventHandler
End Control
Control TextLog Inherits TextArea
ControlInstance TextLog Inherits TextArea
End Control
EventHandler Sub Open() self.Height = 200 End EventHandler
Function FileClose() As Boolean close Return True End Function
Sub ShowLog(r as FMResponseMBS) Self.Height = 400 textlog.Text = ReplaceLineEndings(r.DebugMessages, EndOfLine) TextLog.Visible = True End Sub
Note "Contacts Database"
We use the english version of Contacts database in FileMaker Pro for testing. So in FileMaker, create new database and select Contacts example.
End Class
Class RecordsWindow Inherits Window
Control List Inherits Listbox
ControlInstance List Inherits Listbox
End Control
Sub Setup(Result as Dictionary) Var dataInfo As Dictionary = Result.Lookup("dataInfo", Nil) If dataInfo = Nil Then Break Return End If Var databaseName As String = dataInfo.Value("database") Var layoutName As String = dataInfo.Value("layout") Var tableName As String = dataInfo.Value("table") Var totalRecordCount As Integer = dataInfo.Value("totalRecordCount") Var foundCount As Integer = dataInfo.Value("foundCount") Var returnedCount As Integer = dataInfo.Value("returnedCount") Title = Str(returnedCount)+" of "+Str(foundCount)+" found of "+Str(totalRecordCount)+" records in "+tableName Var Data() As Variant = result.Lookup("data", Nil) Var fields() As String For Each record As Dictionary In data Var recordID As String = record.Value("recordId") Var modId As Integer = record.Value("modId") Var fieldData As Dictionary = record.Value("fieldData") Var portalData As Dictionary = record.Value("portalData") Var c As Integer = fieldData.Count If fields.Ubound < 0 Then // first time Var keys() As Variant = fieldData.keys For Each key As String In keys fields.Append key Next // set listbox heading List.ColumnCount = c For i As Integer = 0 To c-1 List.Heading(i) = fields(i) Next End If list.AddRow "" For i As Integer = 0 To c-1 List.Cell(List.LastIndex, i) = fieldData.Value(fields(I)) Next List.RowTag(list.LastIndex) = recordID Next End Sub
End Class
Sign
End Sign
End Project

See also:

Download this example: FileMaker Data API Test.zip

The items on this page are in the following plugins: MBS CURL Plugin.


The biggest plugin in space...