{"id":23749313,"url":"https://github.com/starsite/swiftfm","last_synced_at":"2025-09-04T22:31:48.897Z","repository":{"id":63920559,"uuid":"148423783","full_name":"starsite/SwiftFM","owner":"starsite","description":"SwiftFM is a Swift framework for the FileMaker Data API","archived":false,"fork":false,"pushed_at":"2024-03-01T20:34:30.000Z","size":247,"stargazers_count":62,"open_issues_count":1,"forks_count":8,"subscribers_count":14,"default_branch":"main","last_synced_at":"2025-08-16T14:47:12.271Z","etag":null,"topics":["api","claris","data-api","filemaker","ios","ipados","macos","rest","server","swift","swiftui","xcode"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/starsite.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":"FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"custom":"https://paypal.me/starsite"}},"created_at":"2018-09-12T04:58:31.000Z","updated_at":"2025-08-15T03:31:20.000Z","dependencies_parsed_at":"2024-03-01T21:44:23.833Z","dependency_job_id":null,"html_url":"https://github.com/starsite/SwiftFM","commit_stats":{"total_commits":114,"total_committers":2,"mean_commits":57.0,"dds":0.0964912280701754,"last_synced_commit":"6bfd5d0aba50afcf6267b2ecfcf09c7671d391b3"},"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"purl":"pkg:github/starsite/SwiftFM","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starsite%2FSwiftFM","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starsite%2FSwiftFM/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starsite%2FSwiftFM/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starsite%2FSwiftFM/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/starsite","download_url":"https://codeload.github.com/starsite/SwiftFM/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starsite%2FSwiftFM/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273684696,"owners_count":25149717,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-04T02:00:08.968Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","claris","data-api","filemaker","ios","ipados","macos","rest","server","swift","swiftui","xcode"],"created_at":"2024-12-31T15:16:30.700Z","updated_at":"2025-09-04T22:31:43.883Z","avatar_url":"https://github.com/starsite.png","language":"Swift","funding_links":["https://paypal.me/starsite"],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"https://starsite.co/swift-fm-hero.png\" alt=\"alt text\" title=\"Starsite Labs\" width=\"100%\" /\u003e\n\n![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/starsite/SwiftFM) ![GitHub](https://img.shields.io/github/license/starsite/SwiftFM) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fstarsite%2FSwiftFM%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/starsite/SwiftFM) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fstarsite%2FSwiftFM%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/starsite/SwiftFM)\n\n# SwiftFM\n\nSwiftFM is a Swift Package for the FileMaker Data API. It uses modern Swift features like `async/await`, `Codable` type-safe returns, and has extensive support for `DocC`.\n\nThis `README.md` is aimed at Swift devs who want to use the Data API in their UIKit and SwiftUI projects. Each function shown below is paired with a code example.\n\nSwiftFM is **in no way** related to the FIleMaker iOS App SDK.\n\n---\n\n### 🗳 How To Use\n\n* Xcode -\u003e File -\u003e Add Packages\n* `https://github.com/starsite/SwiftFM.git`\n* **UIKit**: Set your enivronment in `applicationWillEnterForeground(_:)`\n* **SwiftUI**: Set your enivronment in `MyApp.init()`\n* Add an `import SwiftFM` statement\n* Call `SwiftFM.newSession()` and get a token ✨\n* Woot!\n\n---\n\n### 🖐 How To Help\n\nIf you'd like to support the SwiftFM project, you can:\n\n* Contribute socially, by giving SwiftFM a ⭐️ on GitHub or telling other people about it\n* Contribute [financially](https://paypal.me/starsite) (paypal.me/starsite)\n* Hire me to build an iOS app for you or one of your FileMaker clients. 🥰\n\n---\n\n### ✅ Async/await\n\nSwiftFM was rewritten last year to use `async/await`. This requires Swift 5.5 and iOS 15. If you need to compile for iOS 13 or 14, skip SPM and download the repo instead, and convert the `URLSession` calls using `withCheckedContinuation`. For more information on *that*, visit: [Swift by Sundell](https://wwdcbysundell.com/2021/wrapping-completion-handlers-into-async-apis/), [Hacking With Swift](https://www.hackingwithswift.com/quick-start/concurrency/how-to-use-continuations-to-convert-completion-handlers-into-async-functions), or watch Apple's WWDC 2021 [session](https://developer.apple.com/videos/play/wwdc2021/10132/) on the topic.\n\n---\n\n### 📔 Table of Contents\n\n* [`environment variables`](#environment-variables)\n* [`newSession()`](#-new-session-function---token)\n* [`validateSession(token:)`](#validate-session-function---bool)\n* [`deleteSession(token:)`](#delete-session-function---escaping-bool)\n* [`createRecord(layout:payload:token:)`](#-create-record-function---recordid)\n* [`duplicateRecord(id:layout:token:)`](#duplicate-record-function---recordid)\n* [`editRecord(id:layout:payload:token:)`](#edit-record-function---modid)\n* [`deleteRecord(id:layout:token:)`](#-delete-record-function---bool)\n* [`query(layout:payload:token:)`](#-query-function---record-datainfo)\n* [`getRecords(layout:limit:sortField:ascending:portal:token:)`](#get-records-function---record-datainfo)\n* [`getRecord(id:layout:token:)`](#get-record-function---record-datainfo)\n* [`setGlobals(payload:token:)`](#set-globals-function---bool)\n* [`getProductInfo()`](#get-product-info-function---productinfo)\n* [`getDatabases()`](#get-databases-function---databases)\n* [`getLayouts(token:)`](#get-layouts-function---layouts)\n* [`getLayoutMetaData(layout:token:)`](#get-layout-metadata-function---response)\n* [`getScripts(token:)`](#get-scripts-function---scripts)\n* [`executeScript(script:parameter:layout:token:)`](#execute-script-function---bool)\n* [`setContainer(recordId:layout:container:filePath:inferType:token:)`](#set-container-function---filename)\n\n---\n\n### Environment Variables\n\nFor TESTING, you can set these with string literals. For PRODUCTION, you should be getting these values from elsewhere. DO NOT deploy apps with credentials visible in code. 😵\n\n#### Example: Swift (UIKit)\n\nSet your environment in `AppDelegate` inside `applicationWillEnterForeground(_:)`.\n\n```swift\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n    // ...\n    \n    func applicationWillEnterForeground(_ application: UIApplication) {\n        let host = \"my.host.com\"  //\n        let db   = \"my_database\"  //\n                                  //  fetch these from elsewhere or prompt at launch\n        let user = \"username\"     //\n        let pass = \"password\"     //\n\n        UserDefaults.standard.set(host, forKey: \"fm-host\")\n        UserDefaults.standard.set(db, forKey: \"fm-db\")\n        \n        let str = \"\\(user):\\(pass)\"\n        \n        if let auth = str.data(using: .utf8)?.base64EncodedString() {\n            UserDefaults.standard.set(auth, forKey: \"fm-auth\")\n        }\n    }\n    \n    // ...\n}\n```\n\n#### Example: SwiftUI\n\nSet your environment in `MyApp: App`. If you don't see an `init()` function, add one and finish it out like this.\n\n```swift\n@main\nstruct MyApp: App {        \n    \n    init() {\n        let host = \"my.host.com\"  //\n        let db   = \"my_database\"  //\n                                  //  fetch these from elsewhere or prompt at launch\n        let user = \"username\"     //\n        let pass = \"password\"     //\n\n        UserDefaults.standard.set(host, forKey: \"fm-host\")\n        UserDefaults.standard.set(db, forKey: \"fm-db\")\n        \n        let str = \"\\(user):\\(pass)\"\n        \n        if let auth = str.data(using: .utf8)?.base64EncodedString() {\n            UserDefaults.standard.set(auth, forKey: \"fm-auth\")\n        }\n    }\n    \n    var body: some Scene {\n        // ...\n    }\n}\n```\n\n---\n\n### ✨ New Session (function) -\u003e .token?\n\nReturns an optional `token`.\n\nIf this fails due to an incorrect `Authorization`, the FileMaker Data API will return an error `code` and `message` to the console. All SwiftFM calls output a simple success or failure message.\n\n```swift\nfunc newSession() async -\u003e String? {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let auth = UserDefaults.standard.string(forKey: \"fm-auth\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/sessions\")\n\n    else { return nil }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"POST\"\n    request.setValue(\"Basic \\(auth)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMSession.self, from: data),\n            let message   = result.messages.first\n\n    else { return nil }\n\n    // return\n    switch message.code {\n    case \"0\":\n        guard let token = result.response.token else { return nil }\n\n        UserDefaults.standard.set(token, forKey: \"fm-token\")\n        print(\"✨ new token » \\(token)\")\n\n        return token\n\n    default:\n        print(message)\n        return nil\n    }\n}\n```\n\n#### Example\n\n```swift\nif let token = await SwiftFM.newSession() {\n    print(\"✨ new token » \\(token)\")\n}\n```\n\n---\n\n### Validate Session (function) -\u003e Bool\n\nFileMaker Data API 19 or later. Returns a `Bool`. This function isn't all that useful on its own. But you can use it to wrap *other* calls to ensure they're fired with a valid `token`.\n\n```swift\nfunc validateSession(token: String) async -\u003e Bool {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/validateSession\")\n\n    else { return false }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"GET\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMSession.self, from: data),\n            let message   = result.messages.first\n\n    else { return false }\n\n    // return\n    switch message.code {\n    case \"0\":\n        print(\"✅ valid token » \\(token)\")\n        return true\n\n    default:\n        print(message)\n        return false\n    }\n}\n```\n\n#### Example\n\n```swift\nlet token   = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\nlet isValid = await SwiftFM.validateSession(token: token)\n\nswitch isValid {\ncase true:\n    fetchArtists(token: token)\n\ncase false:\n    if let newToken = await SwiftFM.newSession() {\n       fetchArtists(token: newToken)\n    }       \n}\n```\n\n---\n\n\n### Delete Session (function) -\u003e @escaping Bool\n\nReturns a `Bool`. For standard Swift (UIKit) apps, a good place to call this would be `applicationDidEnterBackground(_:)`. For SwiftUI apps, you should call it inside a `\\.scenePhase.background` switch. \n\nFileMaker's Data API has a 500-session limit, so managing session tokens will be important for larger deployments. If you don't delete your session token, it ~~will~~ *should* expire 15 minutes after the last API call. Probably. But you should clean up after yourself and not assume this will happen. 🙂\n\n```swift\nfunc deleteSession(token: String, completion: @escaping (Bool) -\u003e Void) {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/sessions/\\(token)\")\n\n    else { return }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"DELETE\"\n\n    URLSession.shared.dataTask(with: request) { data, resp, error in\n\n        guard   let data    = data, error == nil,\n                let result  = try? JSONDecoder().decode(FMSession.self, from: data),\n                let message = result.messages.first\n\n        else { return }\n\n        // return\n        switch message.code {\n        case \"0\":\n            UserDefaults.standard.set(nil, forKey: \"fm-token\")\n\n            print(\"🔥 deleted token » \\(token)\")\n            completion(true)\n\n        default:\n            print(message)\n            completion(false)\n        }\n\n    }.resume()\n}\n```\n\n#### Example: Swift (UIKit)\n\n```swift\n@UIApplicationMain\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n// ...\n\n    func applicationDidEnterBackground(_ application: UIApplication) {\n        if let token = UserDefaults.standard.string(forKey: \"fm-token\") {\n            SwiftFM.deleteSession(token: token) { _ in }\n        }\n    }\n    // ...\n}\n```\n\n#### Example: SwiftUI\n\n```swift\n@main\nstruct MyApp: App {\n\n    var body: some Scene {\n        WindowGroup {\n            ContentView()\n        }\n        .onChange(of: scenePhase) { phase in\n            switch phase {\n            case .background:\n                DispatchQueue.global(qos: .background).async {  // extra time\n                    if let token = UserDefaults.standard.string(forKey: \"fm-token\") {\n                        SwiftFM.deleteSession(token: token) { _ in }\n                    }                    \n                }\n            default: break\n            }\n        }\n    }  // .body\n}\n```\n\n---\n\n\n### ✨ Create Record (function) -\u003e .recordId?\n\nReturns an optional `recordId`. This can be called with or without a payload. If you set a `nil` payload, a new empty record will be created. Either method will return a `recordId`. Set your payload with a `[String: Any]` object containing a `fieldData` key.\n\n```swift\nfunc createRecord(layout: String, payload: [String: Any]?, token: String) async -\u003e String? {\n\n    var fieldData: [String: Any] = [\"fieldData\": [:]]  // nil payload\n\n    if let payload {  // non-nil payload\n        fieldData = payload\n    }\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/layouts/\\(layout)/records\"),\n            let body = try? JSONSerialization.data(withJSONObject: fieldData)\n\n    else { return nil }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"POST\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n    request.httpBody = body\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMRecord.self, from: data),\n            let message   = result.messages.first\n\n    else { return nil }\n\n    // return\n    switch message.code {\n    case \"0\":\n        guard let recordId = result.response.recordId else { return nil }\n\n        print(\"✨ new recordId: \\(recordId)\")\n        return recordId\n\n    default:\n        print(message)\n        return nil\n    }\n}\n```\n\n#### Example\n\n```swift\nlet token  = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\nlet layout = \"Artists\"\n\nlet payload = [\"fieldData\": [  // required key\n    \"firstName\": \"Brian\",\n    \"lastName\": \"Hamm\",\n    \"email\": \"hello@starsite.co\"\n]]\n\nif let recordId = await SwiftFM.createRecord(layout: layout, payload: payload, token: token) {\n    print(\"created record: \\(recordId)\")\n}\n```\n\n---\n\n\n### Duplicate Record (function) -\u003e .recordId?\n\nFileMaker Data API 18 or later. Pretty simple call. Returns an optional `recordId` for the new record.\n\n```swift\nfunc duplicateRecord(id: Int, layout: String, token: String) async -\u003e String? {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/layouts/\\(layout)/records/\\(id)\")\n\n    else { return nil }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"POST\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMRecord.self, from: data),\n            let message   = result.messages.first\n\n    else { return nil }\n\n    // return\n    switch message.code {\n    case \"0\":\n        guard let recordId = result.response.recordId else { return nil }\n\n        print(\"✨ new recordId: \\(recordId)\")\n        return recordId\n\n    default:\n        print(message)\n        return nil\n    }\n}\n```\n\n#### Example\n\n```swift\nlet token  = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\nlet recid  = 12345\nlet layout = \"Artists\"\n\nif let recordId = await SwiftFM.duplicateRecord(id: recid, layout: layout, token: token) {\n    print(\"new record: \\(recordId)\")\n}\n```\n\n------\n\n### Edit Record (function) -\u003e .modId?\n\nReturns an optional `modId`. Pass a `[String: Any]` object with a `fieldData` key containing the fields you want to modify.\n\n⚠️ If you include the `modId` value in your `payload` (from say, an earlier fetch), the record will only be modified if the `modId` matches the value on FileMaker Server. This ensures you're working with the current version of the record. If you do **not** pass a `modId`, your changes will be applied without this check.\n\nNote: The FileMaker Data API does not pass back a modified record object for you to use. So you might want to refetch the updated record afterward with `getRecord(id:)`.\n\n```swift\nfunc editRecord(id: Int, layout: String, payload: [String: Any], token: String) async -\u003e String? {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/layouts/\\(layout)/records/\\(id)\"),\n            let body = try? JSONSerialization.data(withJSONObject: payload)\n\n    else { return nil }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"PATCH\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n    request.httpBody = body\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMRecord.self, from: data),\n            let message   = result.messages.first\n\n    else { return nil }\n\n    // return\n    switch message.code {\n    case \"0\":\n        guard let modId = result.response.modId else { return nil }\n\n        print(\"updated modId: \\(modId)\")\n        return modId\n\n    default:\n        print(message)\n        return nil\n    }\n}\n```\n\n#### Example\n\n```swift\nlet token  = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\nlet recid  = 12345\nlet layout = \"Artists\"\n\nlet payload = [\"fieldData\": [\n    \"address\": \"My updated address\",\n]]\n\nif let modId = await SwiftFM.editRecord(id: recid, layout: layout, payload: payload, token: token) {\n    print(\"updated modId: \\(modId)\")\n}\n```\n\n---\n\n### 🔥 Delete Record (function) -\u003e Bool\n\nPretty self explanatory. Returns a `Bool`.\n\n```swift\nfunc deleteRecord(id: Int, layout: String, token: String) async -\u003e Bool {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/layouts/\\(layout)/records/\\(id)\")\n\n    else { return false }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"DELETE\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMBool.self, from: data),\n            let message   = result.messages.first\n\n    else { return false }\n\n    // return\n    switch message.code {\n    case \"0\":\n        print(\"deleted recordId: \\(id)\")\n        return true\n\n    default:\n        print(message)\n        return false\n    }\n}\n```\n\n#### Example\n\n⚠️ This is Swift, not FileMaker. Nothing will prevent this from firing—immediately. Put some kind of confirmation view in your app.\n\n```swift\nlet token  = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\nlet recid  = 12345\nlet layout = \"Artists\"\n\nlet result = await SwiftFM.deleteRecord(id: recid, layout: layout, token: token)\n    \nif result == true {\n    print(\"deleted recordId \\(recordId)\")\n}\n```\n\n------\n\n### 🔍 Query (function) -\u003e ([record], .dataInfo)\n\nReturns a `record` array and `dataInfo` response. This is our first function that returns a **tuple**. You can use either object (or both). The `dataInfo` object includes metadata about the request (database, layout, and table; as well as record count values for total, found, and returned). If you want to ignore `dataInfo`, you can assign it an underscore.\n\nYou can set your `payload` from the UI, or hardcode a query. Then pass it as a `[String: Any]` object with a `query` key.\n\n```swift\nfunc query(layout: String, payload: [String: Any], token: String) async throws -\u003e (Data, FMResult.DataInfo) {\n            \n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/layouts/\\(layout)/_find\"),\n            let body = try? JSONSerialization.data(withJSONObject: payload)\n    \n    else { throw FMError.jsonSerialization }\n    \n    var request = URLRequest(url: url)\n    request.httpMethod = \"POST\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n    request.httpBody = body\n    \n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let json      = try? JSONSerialization.jsonObject(with: data) as? [String: Any],\n            let result    = try? JSONDecoder().decode(FMResult.self, from: data),  // .dataInfo\n            let response  = json[\"response\"] as? [String: Any],\n            let messages  = json[\"messages\"] as? [[String: Any]],\n            let message   = messages[0][\"message\"] as? String,\n            let code      = messages[0][\"code\"] as? String\n    \n    else { throw FMError.sessionResponse }\n        \n    // return\n    switch code {\n    case \"0\":\n        guard   let data     = response[\"data\"] as? [[String: Any]],\n                let records  = try? JSONSerialization.data(withJSONObject: data),\n                let dataInfo = result.response.dataInfo\n\n        else { throw FMError.jsonSerialization }\n        \n        print(\"fetched \\(dataInfo.foundCount) records\")\n        return (records, dataInfo)\n        \n    default:\n        print(message)\n        throw FMError.nonZeroCode\n    }\n}\n```\n\n#### Example\n\nNote the difference in payload between an \"or\" request vs. an \"and\" request. \n\n```swift\nlet token  = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\nlet layout = \"Artists\"\n\n// find artists named Brian or Geoff\nlet payload = [\"query\": [\n    [\"firstName\": \"Brian\"],\n    [\"firstName\": \"Geoff\"]\n]]\n\n// find artists named Brian in Dallas\nlet payload = [\"query\": [\n    [\"firstName\": \"Brian\", \"city\": \"Dallas\"]\n]]\n\nguard   let (data, _) = try? await SwiftFM.query(layout: layout, payload: payload, token: token),\n        let records   = try? JSONDecoder().decode([Artist].self, from: data) \n        \nelse { return }\n\nself.artists = records  // set @State data source\n```\n\n---\n\n### Get Records (function) -\u003e ([record], .dataInfo)\n\nReturns a `record` array and `dataInfo` response. All SwiftFM record fetching methods return a tuple.\n\n```swift\nfunc getRecords(layout: String,\n                limit: Int,\n                sortField: String,\n                ascending: Bool,\n                portal: String?,\n                token: String) async throws -\u003e (Data, FMResult.DataInfo) {\n    \n    \n    // param str\n    let order = ascending ? \"ascend\" : \"descend\"\n    \n    let sortJson = \"\"\"\n    [{\"fieldName\":\"\\(sortField)\",\"sortOrder\":\"\\(order)\"}]\n    \"\"\"\n    \n    var portalJson = \"[]\"  // nil portal\n    \n    if let portal {  // non-nil portal\n        portalJson = \"\"\"\n        [\"\\(portal)\"]\n        \"\"\"\n    }\n            \n    \n    // encoding\n    guard   let sortEnc   = sortJson.urlEncoded,\n            let portalEnc = portalJson.urlEncoded,\n            let host      = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db        = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url       = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/layouts/\\(layout)/records/?_limit=\\(limit)\u0026_sort=\\(sortEnc)\u0026portal=\\(portalEnc)\")\n    \n    else { throw FMError.urlEncoding }\n    \n    \n    // request\n    var request = URLRequest(url: url)\n    request.httpMethod = \"GET\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n    \n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let json      = try? JSONSerialization.jsonObject(with: data) as? [String: Any],\n            let result    = try? JSONDecoder().decode(FMResult.self, from: data),  // .dataInfo\n            let response  = json[\"response\"] as? [String: Any],\n            let messages  = json[\"messages\"] as? [[String: Any]],\n            let message   = messages[0][\"message\"] as? String,\n            let code      = messages[0][\"code\"] as? String\n                \n    else { throw FMError.sessionResponse }\n    \n    \n    // return\n    switch code {\n    case \"0\":\n        guard  let data     = response[\"data\"] as? [[String: Any]],\n               let records  = try? JSONSerialization.data(withJSONObject: data),\n               let dataInfo = result.response.dataInfo\n\n        else { throw FMError.jsonSerialization }\n        \n        print(\"fetched \\(dataInfo.foundCount) records\")\n        return (records, dataInfo)\n        \n    default:\n        print(message)\n        throw FMError.nonZeroCode\n    }\n}\n```\n\n#### Example (SwiftUI)\n\n✨ I'm including a complete SwiftUI example this time, showing the `model`, `view`, and a `fetchArtists(token:)` method. For those unfamiliar with SwiftUI, it's helpful to start in the middle of the example code and work your way out. Here's the gist:\n\nThere is a `.task` on `List` which will return data (async) from FileMaker. I'm using that to set our `@State var artists` array. When a `@State` property is modified, any view depending on it will be called again. In our case, this recalls `body`, refreshing `List` with our record data. Neat.\n\n```swift\n// model\nstruct Artist: Codable {\n    let recordId: String    // ✨ useful as a \\.keyPath in List views\n    let modId: String\n    let fieldData: FieldData\n    \n    struct FieldData: Codable {\n        let name: String      \n    }\n}\n\n// view\nstruct ContentView: View {\n\n    let token = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\n  \n    // our data source\n    @State private var artists = [Artist]()\n  \n    var body: some View {\n        NavigationView {\n          \n            List(artists, id: \\.recordId) { artist in\n                Text(artist.fieldData.name)    // 🥰 type-safe, Codable properties\n            }\n            .navigationTitle(\"Artists\")\n            .task {  // ✅ \u003c-- start here\n                let isValid = await SwiftFM.validateSession(token: token)\n\n                switch isValid {                    \n                case true:\n                    await fetchArtists(token: token)\n\n                case false:\n                    if let newToken = await SwiftFM.newSession() {\n                        await fetchArtists(token: newToken)\n                    }                        \n                }\n            }  // .list            \n        }\n    }\n    // ...\n\n    // fetch 20 artists\n    func fetchArtists(token: String) async {\n\n        guard   let (data, _) = try? await SwiftFM.getRecords(layout: \"Artists\", limit: 20, sortField: \"name\", ascending: true, portal: nil, token: token)\n                let records   = try? JSONDecoder().decode([Artist].self, from: data) \n                \n        else { return }\n\n        self.artists = records  // sets our @State artists array 👆\n    }\n    // ...\n}\n```\n\n- - -\n\n\n### Get Record (function) -\u003e (record, .dataInfo)\n\nReturns a `record` and `dataInfo` response.\n\n```swift\nfunc getRecord(id: Int, layout: String, token: String) async throws -\u003e (Data, FMResult.DataInfo) {\n    \n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/layouts/\\(layout)/records/\\(id)\")\n    \n    else { throw FMError.urlEncoding }\n    \n    var request = URLRequest(url: url)\n    request.httpMethod = \"GET\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n    \n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let json      = try? JSONSerialization.jsonObject(with: data) as? [String: Any],\n            let result    = try? JSONDecoder().decode(FMResult.self, from: data),  // .dataInfo\n            let response  = json[\"response\"] as? [String: Any],\n            let messages  = json[\"messages\"] as? [[String: Any]],\n            let message   = messages[0][\"message\"] as? String,\n            let code      = messages[0][\"code\"] as? String\n                \n    else { throw FMError.sessionResponse }\n    \n    // return\n    switch code {\n    case \"0\":\n        guard  let data     = response[\"data\"] as? [[String: Any]],\n               let data0    = data.first,\n               let record   = try? JSONSerialization.data(withJSONObject: data0),\n               let dataInfo = result.response.dataInfo\n\n        else { throw FMError.jsonSerialization }\n        \n        print(\"fetched recordId: \\(id)\")\n        return (record, dataInfo)\n        \n    default:\n        print(message)\n        throw FMError.nonZeroCode\n    }\n}\n```\n\n#### Example\n\n```swift\nlet token  = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\nlet recid  = 12345\nlet layout = \"Artists\"\n\nguard   let (data, _) = try? await SwiftFM.getRecord(id: recid, layout: layout, token: token),\n        let record    = try? JSONDecoder().decode(Artist.self, from: data) \n        \nelse { return }\n\nself.artist = record\n```\n\n- - -\n\n\n### Set Globals (function) -\u003e Bool\n\nFileMaker Data API 18 or later. Returns a `Bool`. Make this call with a `[String: Any]` object containing a `globalFields` key.\n\n```swift\nfunc setGlobals(payload: [String: Any], token: String) async -\u003e Bool {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/globals\"),\n            let body = try? JSONSerialization.data(withJSONObject: payload)\n\n    else { return false }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"PATCH\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n    request.httpBody = body\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMBool.self, from: data),\n            let message   = result.messages.first\n\n    else { return false }\n\n    // return\n    switch message.code {\n    case \"0\":\n        print(\"globals set\")\n        return true\n\n    default:\n        print(message)\n        return false\n    }\n}\n```\n\n#### Example\n\n⚠️ Global fields must be set using fully qualified field names, ie. `table name::field name`. Also note that our result is a `Bool` and doesn't need to be unwrapped.\n\n```swift\nlet token = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\n\nlet payload = [\"globalFields\": [\n    \"baseTable::gField\": \"newValue\",\n    \"baseTable::gField2\": \"newValue\"\n]]\n\nlet result = await SwiftFM.setGlobals(payload: payload, token: token)\n\nif result == true {\n    print(\"globals set\")\n}\n```\n\n------\n\n### Get Product Info (function) -\u003e .productInfo?\n\nFileMaker Data API 18 or later. Returns an optional `.productInfo` object.\n\n```swift\nfunc getProductInfo() async -\u003e FMProduct.ProductInfo? {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/productInfo\")\n\n    else { return nil }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"GET\"\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMProduct.self, from: data),\n            let message   = result.messages.first\n\n    else { return nil }\n\n    // return\n    switch message.code {\n    case \"0\":\n        let info = result.response.productInfo\n        print(\"product: \\(info.name) (\\(info.version))\")\n\n        return info\n\n    default:\n        print(message)\n        return nil\n    }\n}\n```\n\n#### Example\n\nThis call doesn't require a token.\n\n```swift\nguard let info = await SwiftFM.getProductInfo() else { return }\n\nprint(info.version)  // properties for .name .buildDate, .dateFormat, .timeFormat, and .timeStampFormat\n```\n\n------\n\n### Get Databases (function) -\u003e .databases?\n\nFileMaker Data API 18 or later. Returns an optional array of `.database` objects.\n\n```swift\nfunc getDatabases() async -\u003e [FMDatabases.Database]? {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases\")\n\n    else { return nil }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"GET\"\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMDatabases.self, from: data),\n            let message   = result.messages.first\n\n    else { return nil }\n\n    // return\n    switch message.code {\n    case \"0\":\n        let databases = result.response.databases\n\n        print(\"\\(databases.count) databases\")\n        return databases\n\n    default:\n        print(message)\n        return nil\n    }\n}\n```\n\n#### Example\n\nThis call doesn't require a token.\n\n```swift\nguard let databases = await SwiftFM.getDatabases() else { return }\n\nprint(\"\\nDatabases:\")\n_ = databases.map{ print($0.name) }  // like a .forEach, but shorter\n```\n\n------\n\n### Get Layouts (function) -\u003e .layouts?\n\nFileMaker Data API 18 or later. Returns an optional array of `.layout` objects.\n\n```swift\nfunc getLayouts(token: String) async -\u003e [FMLayouts.Layout]? {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/layouts\")\n\n    else { return nil }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"GET\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMLayouts.self, from: data),\n            let message   = result.messages.first\n\n    else { return nil }\n\n    // return\n    switch message.code {\n    case \"0\":\n        let layouts = result.response.layouts\n\n        print(\"\\(layouts.count) layouts\")\n        return layouts\n\n    default:\n        print(message)\n        return nil\n    }\n}\n```\n\n#### Example\n\nMany SwiftFM result types conform to `Comparable`. 🥰  As such, you can use methods like `.sorted()`, `min()`, and `max()`.\n\n```swift\nlet token = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\n\nguard let layouts = await SwiftFM.getLayouts(token: token) else { return }\n\n// filter and sort folders\nlet folders = layouts.filter{ $0.isFolder == true }.sorted()\n\nfolders.forEach { folder in\n    print(\"\\n\\(folder.name)\")\n\n    // tab indent folder contents\n    if let items = folder.folderLayoutNames?.sorted() {\n        items.forEach { item in\n            print(\"\\t\\(item.name)\")\n        }\n    }\n}\n```\n\n------\n\n### Get Layout Metadata (function) -\u003e .response?\n\nFileMaker Data API 18 or later. Returns an optional `.response` object, containing `.fields` and `.valueList` data. A `.portalMetaData` object is included as well, but will be unique to your FileMaker schema. So you'll need to model that yourself.\n\n```swift\nfunc getLayoutMetadata(layout: String, token: String) async -\u003e FMLayoutMetaData.Response? {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/layouts/\\(layout)\")\n\n    else { return nil }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"GET\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMLayoutMetaData.self, from: data),\n            let message   = result.messages.first\n\n    else { return nil }\n\n    // return\n    switch message.code {\n    case \"0\":\n        if let fields = result.response.fieldMetaData {\n            print(\"\\(fields.count) fields\")\n        }\n\n        if let valueLists = result.response.valueLists {\n            print(\"\\(valueLists.count) value lists\")\n        }\n\n        return result.response\n\n    default:\n        print(message)\n        return nil\n    }\n}\n```\n\n#### Example\n\n```swift\nlet token  = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\nlet layout = \"Artists\"\n\nguard let result = await SwiftFM.getLayoutMetadata(layout: layout, token: token) else { return }\n\nif let fields = result.fieldMetaData?.sorted() {\n    print(\"\\nFields:\")\n    _ = fields.map { print($0.name) }\n}\n\nif let valueLists = result.valueLists?.sorted() {\n    print(\"\\nValue Lists:\")\n    _ = valueLists.map { print($0.name) }\n}\n```\n\n------\n\n### Get Scripts (function) -\u003e .scripts?\n\nFileMaker Data API 18 or later. Returns an optional array of `.script` objects.\n\n```swift\nfunc getScripts(token: String) async -\u003e [FMScripts.Script]? {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/scripts\")\n\n    else { return nil }\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"GET\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMScripts.self, from: data),\n            let message   = result.messages.first\n\n    else { return nil }\n\n    // return\n    switch message.code {\n    case \"0\":\n        let scripts = result.response.scripts\n\n        print(\"\\(scripts.count) scripts\")\n        return scripts\n\n    default:\n        print(message)\n        return nil\n    }\n}\n```\n\n#### Example\n\n```swift\nlet token = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\n\nguard let scripts = await SwiftFM.getScripts(token: token) else { return }\n\n// filter and sort folders\nlet folders = scripts.filter{ $0.isFolder == true }.sorted()\n\nfolders.forEach { folder in\n    print(\"\\n\\(folder.name)\")\n\n    // tab indent folder contents\n    if let scripts = folder.folderScriptNames?.sorted() {\n        scripts.forEach { item in\n            print(\"\\t\\(item.name)\")\n        }\n    }\n}\n```\n\n------\n\n### Execute Script (function) -\u003e Bool\n\nReturns a `Bool`.\n\n```swift\nfunc executeScript(script: String, parameter: String?, layout: String, token: String) async -\u003e Bool {\n\n    // parameter\n    var param = \"\"  // nil parameter\n\n    if let parameter {  // non-nil parameter\n        param = parameter\n    }\n\n    // encoded\n    guard   let scriptEnc = script.urlEncoded,  // StringExtension.swift\n            let paramEnc  = param.urlEncoded\n\n    else { return false }\n\n    // url\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/layouts/\\(layout)/script/\\(scriptEnc)?script.param=\\(paramEnc)\")\n\n    else { return false }\n\n    // request\n    var request = URLRequest(url: url)\n    request.httpMethod = \"GET\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMBool.self, from: data),\n            let message   = result.messages.first\n\n    else { return false }\n\n    // return\n    switch message.code {\n    case \"0\":\n\n        print(\"fired script: \\(script)\")\n        return true\n\n    default:\n        print(message)\n        return false\n    }\n}\n```\n\n#### Example\n\n`Script` and `parameter` values are `.urlEncoded`, so spaces and such are ok.\n\n```swift\nlet token  = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\nlet script = \"test script\"\nlet layout = \"Artists\"\n\nlet result = await SwiftFM.executeScript(script: script, parameter: nil, layout: layout, token: token)\n\nif result == true {\n    print(\"fired script: \\(script)\")\n}\n```\n\n------\n\n### Set Container (function) -\u003e fileName?\n\n```swift\nfunc setContainer(recordId: Int,\n                  layout: String,\n                  container: String,\n                  filePath: URL,\n                  inferType: Bool,\n                  token: String) async -\u003e String? {\n\n    guard   let host = UserDefaults.standard.string(forKey: \"fm-host\"),\n            let db   = UserDefaults.standard.string(forKey: \"fm-db\"),\n            let url  = URL(string: \"https://\\(host)/fmi/data/vLatest/databases/\\(db)/layouts/\\(layout)/records/\\(recordId)/containers/\\(container)\")\n\n    else { return nil }\n\n    // request\n    let boundary = UUID().uuidString\n\n    var request = URLRequest(url: url)\n    request.httpMethod = \"POST\"\n    request.setValue(\"Bearer \\(token)\", forHTTPHeaderField: \"Authorization\")\n    request.setValue(\"multipart/form-data; boundary=\\(boundary)\", forHTTPHeaderField: \"Content-Type\")\n\n    // file data\n    guard let fileData = try? Data(contentsOf: filePath) else { return nil }\n    let mimeType = inferType ? fileData.mimeType : \"application/octet-stream\"  // DataExtension.swift\n\n    // body\n    let br = \"\\r\\n\"\n    let fileName = filePath.lastPathComponent     // ✨ \u003c-- method return\n\n    var httpBody = Data()\n    httpBody.append(\"\\(br)--\\(boundary)\\(br)\")\n    httpBody.append(\"Content-Disposition: form-data; name=upload; filename=\\(fileName)\\(br)\")\n    httpBody.append(\"Content-Type: \\(mimeType)\\(br)\\(br)\")\n    httpBody.append(fileData)\n    httpBody.append(\"\\(br)--\\(boundary)--\\(br)\")\n\n    request.setValue(String(httpBody.count), forHTTPHeaderField: \"Content-Length\")\n    request.httpBody = httpBody\n\n    // session\n    guard   let (data, _) = try? await URLSession.shared.data(for: request),\n            let result    = try? JSONDecoder().decode(FMBool.self, from: data),\n            let message   = result.messages.first\n\n    else { return nil }\n\n    // return\n    switch message.code {\n    case \"0\":\n        print(\"container set: \\(fileName)\")\n        return fileName\n\n    default:\n        print(message)\n        return nil\n    }\n}\n```\n\n#### Example\n\nAn `inferType` of `true` will use `DataExtension.swift` (extensions folder) to attempt to set the mime-type automatically. If you don't want this behavior, set `inferType` to `false`, which assigns a default mime-type of \"application/octet-stream\".\n\n```swift\nlet token  = UserDefaults.standard.string(forKey: \"fm-token\") ?? \"\"\nlet recid  = 12345\nlet layout = \"Artists\"\nlet field  = \"headshot\"\n\nguard   let url = URL(string: \"http://starsite.co/brian_memoji.png\"),\n        let fileName = await SwiftFM.setContainer(recordId: recid,\n                                                  layout: layout,\n                                                  container: field,\n                                                  filePath: url,\n                                                  inferType: true,\n                                                  token: token) \nelse { return }\n\nprint(\"container set: \\(fileName)\")\n```\n\n------\n\nStarsite Labs 😘\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstarsite%2Fswiftfm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstarsite%2Fswiftfm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstarsite%2Fswiftfm/lists"}