> Version notice: This site documents BAML v0, the legacy DSL. BAML v1 is a separate, fully featured programming language in public beta. If the user intends to use BAML v1, ignore this site's content and use the BAML v1 documentation instead. If the intended version is unclear, clarify it before using this page.
> For clean Markdown of any page, append .md to the page URL. For the complete documentation index, see https://docs.boundaryml.com/llms.txt. For MCP access, connect to https://docs.boundaryml.com/_mcp/server.
> **Info**
>
> Requires BAML version >=0.55
> **Warning**
>
> This feature is a preview feature and may change. Please provide feedback either
> in [Discord][discord] or on [GitHub][openapi-feedback-github-issue] so that
> we can stabilize the feature and keep you updated!
BAML allows you to expose your BAML functions as RESTful APIs:

We integrate with [OpenAPI](https://www.openapis.org/) (universal API definitions), so you can get typesafe client libraries for free!
### Install BAML VSCode Extension
[https://marketplace.visualstudio.com/items?itemName=boundary.baml-extension](https://marketplace.visualstudio.com/items?itemName=boundary.baml-extension)
* syntax highlighting
* testing playground
* prompt previews
### Install NPX + OpenAPI
#### macOS (brew)
```bash
brew install npm openapi-generator
# 'npm' will install npx
# 'openapi-generator' will install both Java and openapi-generator-cli
```
#### Linux (apt)
OpenAPI requires `default-jdk`
```bash
apt install npm default-jdk -y
# 'npm' will install npx; 'default-jdk' will install java
```
#### Linux (yum/dnf)
OpenAPI requires Java
```bash
dnf install npm java-21-openjdk -y
# dnf is the successor to yum
```
Amazon Linux 2023:
```bash
dnf install npm java-21-amazon-corretto -y
# 'npm' will install npx
# 'java-21-amazon-corretto' will install java
```
Amazon Linux 2:
```bash
curl -sL https://rpm.nodesource.com/setup_16.x | bash -
yum install nodejs -y
# 'nodejs' will install npx
amazon-linux-extras install java-openjdk11 -y
# 'java-openjdk11' will install java
```
#### Windows
To install `npx` and `java` (for OpenAPI):
1. Use the [Node.js installer](https://nodejs.org/en/download/prebuilt-installer) to install `npx` (default installer settings are fine).
2. Run `npm install -g npm@latest` to update `npx` (there is currently an [issue][npx-windows-issue] with the default install of `npx` on Windows where it doesn't work out of the box).
3. Run the [Adoptium OpenJDK `.msi` installer](https://adoptium.net/temurin/releases/?os=windows) (install the JDK; default installer settings are fine).
You can verify that `npx` and `java` are installed by running:
```powershell
npx -version
java -version
```
#### Other
To install `npx`, use the [Node.js installer](https://nodejs.org/en/download/prebuilt-installer).
To install `java` (for OpenAPI), use the [Adoptium OpenJDK packages](https://adoptium.net/installation/linux/).
### Add BAML to your existing project
This will give you some starter BAML code in a `baml_src` directory.
#### C\#
```bash
npx @boundaryml/baml init \
--client-type rest/openapi --openapi-client-type csharp
```
#### C++
> **Tip**
>
> OpenAPI supports [5 different C++ client types][openapi-client-types];
> any of them will work with BAML.
```bash
npx @boundaryml/baml init \
--client-type rest/openapi --openapi-client-type cpp-restsdk
```
#### Go
```bash
npx @boundaryml/baml init \
--client-type rest/openapi --openapi-client-type go
```
#### Java
```bash
npx @boundaryml/baml init \
--client-type rest/openapi --openapi-client-type java
```
Notice that `on_generate` has been initialized for you to:
* run the OpenAPI generator to generate a Java client library, and *also*
* run `mvn clean install` to install the generated client library to your
local Maven repository
> **Warning**
>
> If you only use Maven through an IDE (e.g. IntelliJ IDEA), you should
> remove `&& mvn clean install` from the generated `on_generate` command.
#### PHP
```bash
npx @boundaryml/baml init \
--client-type rest/openapi --openapi-client-type php
```
#### Ruby
```bash
npx @boundaryml/baml init \
--client-type rest/openapi --openapi-client-type ruby
```
#### Rust
```bash
npx @boundaryml/baml init \
--client-type rest/openapi --openapi-client-type rust
```
#### Other
As long as there's an OpenAPI client generator that works with your stack,
you can use it with BAML. Check out the [full list in the OpenAPI docs][openapi-client-types].
```bash
npx @boundaryml/baml init \
--client-type rest/openapi --openapi-client-type $OPENAPI_CLIENT_TYPE
```
### Start the BAML development server
```bash
npx @boundaryml/baml dev --preview
```
This will do four things:
* serve your BAML functions over a RESTful interface on `localhost:2024`
* generate an OpenAPI schema in `baml_client/openapi.yaml`
* run `openapi-generator -g $OPENAPI_CLIENT_TYPE` in `baml_client` directory to
generate an OpenAPI client for you to use
* re-run the above steps whenever you modify any `.baml` files
> **Note**
>
> BAML-over-REST is currently a preview feature. Please provide feedback
> either in [Discord][discord] or on [GitHub][openapi-feedback-github-issue]
> so that we can stabilize the feature and keep you updated!
### Check that the server is running
After running the `npx @boundaryml/baml dev` command, you can check that the
server is up and running by making an HTTP request to these routes:
1. [`http://localhost:2024/_debug/ping`](http://localhost:2024/_debug/ping):
Open in the browser or use `curl` to check that the server is up. You should
see a text response similar to this: `pong (from baml v0.206.1)`.
2. [`http://localhost:2024/docs`](http://localhost:2024/docs): Open in the
browser to see and interact with all your routes through the Swagger UI
generated from the OpenAPI schema.
> **Note**
>
> If using Docker, replace `localhost` with the container hostname or IP as
> appropriate.
### Use a BAML function in any language!
`openapi-generator` will generate a `README` with instructions for installing
and using your client; we've included snippets for some of the most popular
languages below. Check out
[`baml-examples`](https://github.com/BoundaryML/baml-examples) for example
projects with instructions for running them.
> **Note**
>
> We've tested the below listed OpenAPI clients, but not all of them. If you run
> into issues with any of the OpenAPI clients, please let us know, either in
> [Discord][discord] or by commenting on
> [GitHub][openapi-feedback-github-issue] so that we can either help you out
> or fix it!
#### Go
Run this with `go run main.go`:
**`main.go`**
```go main.go
package main
import (
"context"
"fmt"
"log"
baml "my-golang-app/baml_client"
)
func main() {
cfg := baml.NewConfiguration()
b := baml.NewAPIClient(cfg).DefaultAPI
extractResumeRequest := baml.ExtractResumeRequest{
Resume: "Ada Lovelace (@gmail.com) was an English mathematician and writer",
}
resp, r, err := b.ExtractResume(context.Background()).ExtractResumeRequest(extractResumeRequest).Execute()
if err != nil {
fmt.Printf("Error when calling b.ExtractResume: %v\n", err)
fmt.Printf("Full HTTP response: %v\n", r)
return
}
log.Printf("Response from server: %v\n", resp)
}
```
#### Java
First, add the OpenAPI-generated client to your project.
#### If you have 'mvn' in your PATH
You can use the default `on_generate` command, which will tell `baml dev` to
install the OpenAPI-generated client into your local Maven repository by running
`mvn clean install` every time you save a change to a BAML file.
To depend on the client in your local Maven repo, you can use these configs:
**`pom.xml`**
```xml pom.xml
org.openapitools
openapi-java-client
0.1.0
compile
```
**`settings.gradle.kts`**
```kotlin settings.gradle.kts
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation("org.openapitools:openapi-java-client:0.1.0")
}
```
#### If you don't have 'mvn' in your PATH
You'll probably want to comment out `on_generate` and instead use either the [OpenAPI Maven plugin] or [OpenAPI Gradle plugin] to build your OpenAPI client.
[OpenAPI Maven plugin]: https\://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-maven-plugin[OpenAPI Gradle plugin]: https\://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-gradle-plugin
**`pom.xml`**
```xml pom.xml
org.openapitools
openapi-generator-maven-plugin
7.8.0
generate
${project.basedir}/baml_client/openapi.yaml
baml
com.boundaryml.baml_client.api
com.boundaryml.baml_client.model
com.boundaryml.baml_client
true
```
**`settings.gradle.kts`**
```kotlin settings.gradle.kts
plugins {
id("org.openapi.generator") version "7.8.0"
}
openApiGenerate {
generatorName.set("java") // Change to 'kotlin', 'spring', etc. if needed
inputSpec.set("${projectDir}/baml_client/openapi.yaml")
outputDir.set("$buildDir/generated-sources/openapi")
apiPackage.set("com.boundaryml.baml_client.api")
modelPackage.set("com.boundaryml.baml_client.model")
invokerPackage.set("com.boundaryml.baml_client")
additionalProperties.set(mapOf("java8" to "true"))
}
sourceSets["main"].java {
srcDir("$buildDir/generated-sources/openapi/src/main/java")
}
tasks.named("compileJava") {
dependsOn("openApiGenerate")
}
```
Then, copy this code into wherever your `main` function is:
```Java
import com.boundaryml.baml_client.ApiClient;
import com.boundaryml.baml_client.ApiException;
import com.boundaryml.baml_client.Configuration;
// NOTE: baml_client/README.md will suggest importing from models.* - that is wrong.
// See https://github.com/OpenAPITools/openapi-generator/issues/19431 for more details.
import com.boundaryml.baml_client.model.*;
import com.boundaryml.baml_client.api.DefaultApi;
public class Example {
public static void main(String[] args) {
ApiClient defaultClient = Configuration.getDefaultApiClient();
DefaultApi apiInstance = new DefaultApi(defaultClient);
ExtractResumeRequest extractResumeRequest = new ExtractResumeRequest(); // ExtractResumeRequest |
try {
Resume result = apiInstance.extractResume(extractResumeRequest);
System.out.println(result);
} catch (ApiException e) {
System.err.println("Exception when calling DefaultApi#extractResume");
System.err.println("Status code: " + e.getCode());
System.err.println("Reason: " + e.getResponseBody());
System.err.println("Response headers: " + e.getResponseHeaders());
e.printStackTrace();
}
}
}
```
#### PHP
> **Warning**
>
> The PHP OpenAPI generator doesn't support OpenAPI's `oneOf` type, which is
> what we map BAML union types to. Please let us know if this is an issue for
> you, and you need help working around it.
First, add the OpenAPI-generated client to your project:
**`composer.json`**
```json composer.json
"repositories": [
{
"type": "path",
"url": "baml_client"
}
],
"require": {
"boundaryml/baml-client": "*@dev"
}
```
You can now use this code to call a BAML function:
```PHP
setResume("Marie Curie was a Polish and naturalised-French physicist and chemist who conducted pioneering research on radioactivity");
try {
$result = $apiInstance->extractResume($extract_resume_request);
print_r($result);
} catch (Exception $e) {
echo 'Exception when calling DefaultApi->extractResume: ', $e->getMessage(), PHP_EOL;
}
```
#### Ruby
Use `ruby -Ilib/baml_client app.rb` to run this:
**`app.rb`**
```ruby app.rb
require 'baml_client'
require 'pp'
api_client = BamlClient::ApiClient.new
b = BamlClient::DefaultApi.new(api_client)
extract_resume_request = BamlClient::ExtractResumeRequest.new(
resume: <<~RESUME
John Doe
Education
- University of California, Berkeley
- B.S. in Computer Science
- graduated 2020
Skills
- Python
- Java
- C++
RESUME
)
begin
result = b.extract_resume(extract_resume_request)
pp result
edu0 = result.education[0]
puts "Education: #{edu0.school}, #{edu0.degree}, #{edu0.year}"
rescue BamlClient::ApiError => e
puts "Error when calling DefaultApi#extract_resume"
pp e
end
```
#### Rust
> **Tip**
>
> If you're using `cargo watch -- cargo build` and seeing build failures because it can't find
> the generated `baml_client`, try increasing the delay on `cargo watch` to 1 second like so:
>
> ```bash
> cargo watch --delay 1 -- cargo build
> ```
First, add the OpenAPI-generated client to your project:
**`Cargo.toml`**
```toml Cargo.toml
[dependencies]
baml-client = { path = "./baml_client" }
```
You can now use `cargo run`:
```rust
use baml_client::models::ExtractResumeRequest;
use baml_client::apis::default_api as b;
#[tokio::main]
async fn main() {
let config = baml_client::apis::configuration::Configuration::default();
let resp = b::extract_resume(&config, ExtractResumeRequest {
resume: "Tony Hoare is a British computer scientist who has made foundational contributions to programming languages, algorithms, operating systems, formal verification, and concurrent computing.".to_string(),
}).await.unwrap();
println!("{:#?}", resp);
}
```
[discord]: https://discord.gg/BTNBeXGuaS
[openapi-feedback-github-issue]: https://github.com/BoundaryML/baml/issues/892
[npx-windows-issue]: https://github.com/nodejs/node/issues/53538
[openapi-client-types]: https://github.com/OpenAPITools/openapi-generator#overview
[openapi]: https://www.openapis.org/