> For the complete documentation index, see [llms.txt](https://docs.ninox.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ninox.com/ninox-scripting/automate-your-workflows/work-with-functions/integration-and-http.md).

# Integration and HTTP

Integration functions connect your app to services and communication tools outside Ninox. You can call APIs, validate XML against schemas, transform XML, send emails, and create appointments or reminders where the environment supports it.

In this chapter, you will learn how to:

* Call external services with HTTP.
* Transform XML.
* Create appointments.

<table><thead><tr><th width="249.3359375">Function (A-Z)</th><th>Task</th></tr></thead><tbody><tr><td><code>appointment()</code></td><td>Create an appointment value</td></tr><tr><td><code>email()</code></td><td>Return or reuse an email value</td></tr><tr><td><code>formatXML()</code></td><td>Convert JSON data to XML text</td></tr><tr><td><code>http()</code></td><td>Send an HTTP request</td></tr><tr><td><code>parseXML()</code></td><td>Convert XML text to a JSON object</td></tr></tbody></table>

## Call external services

Use these functions to call any REST API, to pull data from another service or push data between Ninox databases.

### Call an API with `http()`

Use `http()` to send a request to an external service.

Use it when you want to:

* Fetch data from, or send updates to another system.
* Connect Ninox to REST APIs and other Ninox databases.

{% hint style="warning" %}
**Don't place `http()` inside `do as transaction...end`**

Transactions use a single-threaded write queue. An HTTP call inside a transaction blocks all other writes until the request finishes. The app does not hang forever, but every pending write waits for the full duration of the call. That can make the app feel slow.
{% endhint %}

`http(method, url)`\
`http(method, url, body)`\
`http(method, url, header, body)`\
`http(method, url, header, body, files)`

* `method` : text value of the HTTP method , for example, `"GET"` or `"POST"`
* `url` : text value of the endpoint URL
* `header`: optional headers as a JSON object, for example, `{ Authorization: token }`
* `body`: optional request body as a JSON object
* `files`: optional files to upload as `[file]` when the current execution context supports file uploads (server context)

{% hint style="warning" %}
**A body is required when accessing Ninox data**

If you use `http()` to access data in Ninox, a body must be passed. If no information needs to be passed in the body, it simply remains empty. An example of this would be:

`http("GET", "https://api.ninox.com/v1/[...]", {Authorization: "Bearer xxxx-xxxx-xxxx", "content-type": "application/json"}, {})`
{% endhint %}

#### Let’s take a look at some examples:

```ninox
http("GET", "https://api.example.com/status")
```

Calls the external service and returns a JSON response object or an error object.

```ninox
let url := "https://api.ninoxdb.de/v1/teams/" + teamId() +
           "/databases/" + databaseId() + "/tables/";
let apiKey := "Bearer abcd1234-0000-xxxx-zzzz-1a1aa1aaa1a111";

let response := http("GET", url, {
    Authorization: apiKey
});
response
```

Lists tables from the current database through the Ninox API or an error object.

```ninox
do as server
   let url := "https://api.ninoxdb.de/v1/teams/" + teamId() +
             "/databases/" + databaseId() + "/query";
   let apiKey := "Bearer abcd1234-0000-xxxx-zzzz-1a1aa1aaa1a111";
   
   let response := http("POST", url, {
             Authorization: apiKey, 
             "content-type": "application/json"
   }, {
    query: "select customers where status = 4"
   });
   response
end
```

Sends a POST request and returns matching records or an error object.

<pre class="language-ninox"><code class="lang-ninox"><strong>let response := do as server
</strong>    http("POST",
        "https://example.com/upload",
        { "content-type": "multipart/form-data" },
        null,
        [myFile])
end
</code></pre>

Uploads a file to an external service when file uploads are supported in the current execution context.

Tips:

* `http()` returns a JSON object, not plain text.
* If you access another Ninox database, you need an API key.
* Some endpoints expect a body even for `GET` requests. Use `{}` when the target endpoint requires one and you do not need to send fields.
* File uploads depend on the execution context.
* Test integration scripts against the real service response, not sample output only.

## Transform XML

Use these functions when another system sends or expects XML, especially when the XML must match a defined schema.

### Convert XML text to data with `parseXML()`

Use `parseXML()` to turn XML text into a JSON object you can inspect in Ninox. This is especially useful when you connect Ninox to external services by API and need to process XML responses. XML is a common exchange format alongside JSON.

Use it when you want to:

* Read values from an XML response.
* Extract fields from imported XML.
* Convert XML into structured data for later logic.

`parseXML(string)`

* `string`: the XML text you want to convert to a JSON object

#### Let’s take a look at some examples:

```ninox
let xml := "<?xml version=""1.0"" encoding=""UTF-8""?>
<note>
    <to>Jane Doe</to>
    <from>Ninox</from>
    <heading>Save the world!</heading>
    <body>Please save the world!</body>
</note>";
parseXML(xml)
```

Returns a JSON object built from the XML text, for example:

```json
{
  "note": {
    "to": {
      "@": "Jane Doe"
    },
    "from": {
      "@": "Ninox"
    },
    "heading": {
      "@": "Save the world!"
    },
    "body": {
      "@": "Please save the world!"
    }
  }
}
```

Tip:

* If you have an XSD schema, validate external XML before you parse it.

### Create XML text with `formatXML()`

Use `formatXML()` to convert JSON data into XML text.

Use it when you want to:

* Prepare XML for another service.
* Reformat parsed data into readable XML.

`formatXML(JSON)`\
`formatXML(JSON, boolean)`

* `JSON`: the structured data you want to convert to XML
* `boolean`: whether the output should be visually structured for reading

#### Let’s take a look at some examples:

```ninox
let x := parseXML("<root><item>1</item></root>");
formatXML(x, true)
```

Formats the parsed object back into readable XML text.

```ninox
formatXML({
    contact: {
        @type: "Person",
        firstName: {
            @: "Max"
        },
        lastName: {
            @: "Mustermann"
        },
        phone: [{
            @type: "Mobile",
            @: "(+1) (202) 123 45 67"
        }, {
            @type: "Phone",
            @: "+1.151.11 ++66 14 66"
        }]
    }
}, true)
```

Converts the JSON object into structured XML text. Keys like `@type` become XML attributes. `@` becomes the node text value.

Tips:

* Use the pretty option when humans need to read the result.
* Use compact output when the target system only needs the payload.
* This function is especially useful for API integrations that expect XML instead of JSON.

## Create appointments

Use these functions when you want to create a time-based item for your workflow.

### Create an appointment value with `appointment()`

Use `appointment()` to convert time-related values into an appointment value.

Use it when you want to:

* Set up a meeting or consultation slot from start and end values.
* Create a time range from a start and a duration.
* Pass a scheduled time range into later logic.

`appointment(any, any)`

* first `any`: the start timestamp
* second `any`: the end timestamp of the appointment or a duration

#### Let’s take a look at some examples:

```ninox
appointment(datetime(2021, 3, 16, 19), datetime(2021, 3, 6, 17))
```

Creates an appointment from two timestamps. Ninox automatically uses the earlier timestamp as the start.

```ninox
appointment(datetime(2021, 5, 22, 10), time(1, 45))
```

Creates an appointment from a start datetime and a duration of 1 hour and 45 minutes.

Tips:

* The argument order does not matter when you pass two timestamps. Ninox uses the earlier one as the start.
* If start and end are on the same day, the display usually shows only one date. If they span multiple days, both dates are shown.

{% hint style="info" %}
Integration behavior can depend on your environment, client, and connected services. Confirm HTTP and email workflows in the same setup your users run in production.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ninox.com/ninox-scripting/automate-your-workflows/work-with-functions/integration-and-http.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
