Groovy is a powerful, dynamic language for the Java platform that blends seamlessly with existing Java code while offering concise syntax and scripting flexibility. One of its most practical use cases is interacting with RESTful APIs—whether for automation, testing, or lightweight backend tasks.
In this tutorial, you’ll learn step by step how to call REST APIs using Groovy. We’ll start with simple GET requests, move on to parsing JSON, sending POST requests with payloads, adding authentication headers, and finally, exploring more advanced libraries to simplify HTTP operations. By the end, you’ll be equipped to build scripts that can communicate with any REST API quickly and efficiently.
1. Prerequisites
Before we dive in, make sure you have the following set up on your machine:
-
Java Development Kit (JDK 17 or higher)
Since Groovy runs on the JVM, you’ll need Java installed. You can check your version with:java -version
-
Groovy (latest version, preferably 4.x)
The easiest way to install Groovy is using SDKMAN!:curl -s "https://get.sdkman.io" | bash source "$HOME/.sdkman/bin/sdkman-init.sh" sdk install groovy
Verify the installation:
groovy -v
-
Basic understanding of REST APIs
You should be familiar with common HTTP methods likeGET
,POST
,PUT
, andDELETE
. -
A REST API to test against
In this tutorial, we’ll use the JSONPlaceholder fake API, which is perfect for practicing GET and POST requests.
👉 Once you have these ready, you’re set to start making API calls with Groovy.
2. Setting Up Groovy
Before we can start calling REST APIs, we need to make sure Groovy is properly installed and ready to use.
Step 1: Install Groovy
There are two common ways to install Groovy:
Option A: Using SDKMAN! (Recommended)
SDKMAN! is a handy tool for managing parallel versions of multiple SDKs. If you don’t already have it installed:
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
Then install Groovy with:
sdk install groovy
Option B: Manual Installation
-
Download the latest Groovy binary from the official Groovy website.
-
Extract the archive to a directory of your choice (e.g.,
/opt/groovy
). -
Add Groovy’s
bin
directory to your system’sPATH
. For example, in Linux/macOS, edit~/.bashrc
or~/.zshrc
:
export PATH=$PATH:/opt/groovy/bin
Step 2: Verify Installation
Once installed, check the Groovy version:
groovy -v
You should see something like:
Groovy Version: 4.0.15 JVM: 17.0.9 Vendor: Oracle OS: Mac OS X
Step 3: Test a Simple Script
Let’s confirm that Groovy is working by running a small script:
Create a file hello.groovy
with the following content:
println "Hello, Groovy!"
Run it with:
groovy hello.groovy
Output:
Hello, Groovy!
✅ Congratulations! Groovy is installed and running. You’re now ready to use it for making HTTP requests.
3. Making a Simple GET Request
The most common operation when working with REST APIs is fetching data using an HTTP GET request. Groovy makes this really simple because it extends Java classes like URL
with helper methods.
Example: Fetching a Post from JSONPlaceholder
def url = new URL("https://jsonplaceholder.typicode.com/posts/1")
def response = url.text
println(response)
Explanation
-
new URL(...)
→ Creates a URL object pointing to the API endpoint. -
.text
→ Groovy adds this shortcut to the JavaURL
class, allowing you to fetch the content directly as a string. -
println(response)
→ Prints the raw JSON response from the API.
Expected Output
When you run the script above (groovy getRequest.groovy
), you’ll see:
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
Why This Works Well
-
No need for extra libraries.
-
Perfect for quick one-liners or automation scripts.
-
You can fetch any public API with just two lines of Groovy.
👉 In the next section, we’ll learn how to parse this JSON response so we can extract specific fields like title
or body
.
4. Parsing JSON Responses
Most REST APIs return data in JSON format. Groovy comes with a built-in class called JsonSlurper
that makes it easy to parse JSON into maps and lists, which you can use just like regular Groovy objects.
Example: Parse a JSON Response
import groovy.json.JsonSlurper
def url = new URL("https://jsonplaceholder.typicode.com/posts/1")
def jsonText = url.text
def json = new JsonSlurper().parseText(jsonText)
println("ID: ${json.id}")
println("User ID: ${json.userId}")
println("Title: ${json.title}")
println("Body: ${json.body}")
Explanation
-
JsonSlurper
→ Groovy’s JSON parser. -
.parseText(jsonText)
→ Converts the JSON string into a Groovy object (usually aMap
). -
${json.title}
→ You can access fields directly like properties.
Expected Output
ID: 1
User ID: 1
Title: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
Body: quia et suscipit
suscipit recusandae consequuntur expedita et cum
reprehenderit molestiae ut ut quas totam
nostrum rerum est autem sunt rem eveniet architecto
Parsing Arrays
Some endpoints return an array of objects instead of a single one. For example:
import groovy.json.JsonSlurper
def url = new URL("https://jsonplaceholder.typicode.com/posts")
def posts = new JsonSlurper().parseText(url.text)
println "Total posts: ${posts.size()}"
println "First post title: ${posts[0].title}"
This will output:
Total posts: 100
First post title: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
✅ Now you can work with API data just like Groovy maps and lists, making it very convenient for automation, reporting, or testing tasks.
5. Sending a POST Request
While GET
is useful for retrieving data, you’ll often need to send data to an API using a POST request. This is common for creating resources (e.g., creating a new user, posting a comment).
In Groovy, you can use HttpURLConnection
to send POST requests and include JSON payloads.
Example: Sending JSON Data
import groovy.json.JsonOutput
def url = new URL("https://jsonplaceholder.typicode.com/posts")
def conn = url.openConnection()
conn.setRequestMethod("POST")
conn.doOutput = true
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8")
// JSON payload
def payload = [
title : "Groovy Post",
body : "Hello from Groovy!",
userId: 1
]
// Write the JSON to the request body
conn.outputStream.withWriter("UTF-8") { writer ->
writer << JsonOutput.toJson(payload)
}
// Read the response
println "Response Code: ${conn.responseCode}"
println "Response: ${conn.inputStream.text}"
Explanation
-
setRequestMethod("POST")
→ Tells the connection we’re sending a POST request. -
setRequestProperty("Content-Type", "application/json")
→ Specifies that we’re sending JSON data. -
JsonOutput.toJson(payload)
→ Converts the Groovy map into a JSON string. -
conn.outputStream.withWriter { ... }
→ Writes the JSON payload to the request body. -
conn.responseCode
andconn.inputStream.text
→ Retrieve the HTTP status code and server response.
Expected Output (from JSONPlaceholder)
Response Code: 201
Response: {
"title": "Groovy Post",
"body": "Hello from Groovy!",
"userId": 1,
"id": 101
}
💡 Note: JSONPlaceholder is a fake API, so it doesn’t actually create new posts—it just returns a mock response with an
id
.
✅ Now you know how to send JSON payloads using POST requests in Groovy.
6. Adding Headers & Authentication
Most real-world APIs require additional headers—for example, specifying the content type, passing an API key, or including a Bearer token for authentication. With Groovy, adding headers is simple.
Example: Adding Custom Headers
def url = new URL("https://jsonplaceholder.typicode.com/posts/1")
def conn = url.openConnection()
// Add custom headers
conn.setRequestProperty("Accept", "application/json")
conn.setRequestProperty("User-Agent", "GroovyClient/1.0")
println "Response Code: ${conn.responseCode}"
println "Response: ${conn.inputStream.text}"
Example: Bearer Token Authentication
When working with secure APIs, you’ll often need to include an Authorization
header.
def url = new URL("https://api.example.com/data")
def conn = url.openConnection()
conn.setRequestMethod("GET")
// Add authorization header
conn.setRequestProperty("Authorization", "Bearer YOUR_ACCESS_TOKEN")
conn.setRequestProperty("Accept", "application/json")
println "Response Code: ${conn.responseCode}"
println "Response: ${conn.inputStream.text}"
Example: API Key in Header
Some APIs use an API key instead of a token:
def url = new URL("https://api.example.com/weather")
def conn = url.openConnection()
conn.setRequestMethod("GET")
conn.setRequestProperty("x-api-key", "YOUR_API_KEY")
println "Response Code: ${conn.responseCode}"
println "Response: ${conn.inputStream.text}"
Why Headers Matter
-
Authorization → Secure access to APIs.
-
Content-Type / Accept → Tell the API the format you’re sending or expecting (JSON, XML, etc.).
-
User-Agent → Identifies your client (sometimes required).
✅ With headers and authentication, you can now access protected APIs just as easily as public ones.
7. Handling Errors & Response Codes
When working with REST APIs, not every request will succeed. You might encounter:
-
404 Not Found (wrong endpoint or resource missing)
-
401 Unauthorized / 403 Forbidden (missing or invalid credentials)
-
500 Internal Server Error (server-side issue)
-
Timeouts or connectivity problems
Groovy lets you inspect response codes and catch exceptions to handle these cases gracefully.
Example: Basic Error Handling
def url = new URL("https://jsonplaceholder.typicode.com/invalid-endpoint")
def conn = url.openConnection()
conn.setRequestMethod("GET")
try {
def responseCode = conn.responseCode
if (responseCode == 200) {
println "Success: ${conn.inputStream.text}"
} else {
println "Error: Response code ${responseCode}"
println "Error details: ${conn.errorStream?.text}"
}
} catch (IOException e) {
println "Exception occurred: ${e.message}"
}
Explanation
-
conn.responseCode
→ Retrieves the HTTP status code. -
conn.inputStream.text
→ Reads the response body (if successful). -
conn.errorStream?.text
→ Reads error details if available (e.g., from a 404 or 500 response). -
try-catch
→ Ensures the script doesn’t crash on network errors.
Example: Handling Authentication Failures
def url = new URL("https://api.example.com/protected")
def conn = url.openConnection()
conn.setRequestMethod("GET")
// Intentionally missing token
conn.setRequestProperty("Accept", "application/json")
try {
if (conn.responseCode == 200) {
println "Response: ${conn.inputStream.text}"
} else if (conn.responseCode == 401 || conn.responseCode == 403) {
println "Authentication failed: ${conn.responseCode}"
} else {
println "Unexpected error: ${conn.responseCode}"
}
} catch (Exception e) {
println "Request failed: ${e.message}"
}
Best Practices for Error Handling
-
Always check
responseCode
before reading the response. -
Use
errorStream
for error details. -
Wrap requests in
try-catch
to handle connectivity issues. -
For production scripts, consider logging instead of just printing.
✅ With proper error handling, your Groovy scripts will be more reliable and easier to debug.
8. Using Groovy’s @Grab
and HTTPBuilder for Cleaner API Calls
While HttpURLConnection
works fine, it can get verbose, especially when handling headers, POST bodies, and responses. Groovy supports Grape (@Grab
), which allows you to fetch external libraries directly from Maven Central, making scripts more powerful without needing a full project setup.
One popular library for REST calls in Groovy is HTTPBuilder.
Example: Using @Grab
to Import HTTPBuilder
Create a script called httpbuilder-example.groovy
:
@Grab('com.squareup.okhttp3:okhttp:4.12.0')
@Grab('com.fasterxml.jackson.core:jackson-databind:2.18.2')
import okhttp3.*
import com.fasterxml.jackson.databind.ObjectMapper
def client = new OkHttpClient()
def mapper = new ObjectMapper()
// GET request
def request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.build()
def response = client.newCall(request).execute()
def json = mapper.readTree(response.body().string())
println "Title: ${json.get('title').asText()}"
println "Body: ${json.get('body').asText()}"
Explanation
-
@Grab
→ Automatically downloads and adds the dependency (http-builder
) at runtime. -
RESTClient
→ Simplifies HTTP operations like GET, POST, PUT, DELETE. -
response.data
→ Parsed JSON response (already converted to Groovy objects).
Example: Sending a POST Request with HTTPBuilder
@Grab('com.squareup.okhttp3:okhttp:4.12.0')
@Grab('com.fasterxml.jackson.core:jackson-databind:2.18.2')
import okhttp3.*
import com.fasterxml.jackson.databind.ObjectMapper
def client = new OkHttpClient()
def mapper = new ObjectMapper()
// GET request
def request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.build()
def response = client.newCall(request).execute()
def json = mapper.readTree(response.body().string())
println "Title: ${json.get('title').asText()}"
println "Body: ${json.get('body').asText()}"
// POST request
def postBody = RequestBody.create(
mapper.writeValueAsString([title: "OkHttp Post", body: "Hello Groovy 4", userId: 1]),
MediaType.get("application/json; charset=utf-8")
)
def postRequest = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts")
.post(postBody)
.build()
def postResponse = client.newCall(postRequest).execute()
println "New Post Response: ${postResponse.body().string()}"
Expected Output (from JSONPlaceholder):
Title: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
Body: quia et suscipit
suscipit recusandae consequuntur expedita et cum
reprehenderit molestiae ut ut quas totam
nostrum rerum est autem sunt rem eveniet architecto
New Post Response: {
"title": "OkHttp Post",
"body": "Hello Groovy 4",
"userId": 1,
"id": 101
}
Why Use HTTPBuilder?
✅ Cleaner syntax for REST calls
✅ Automatic JSON parsing
✅ Easier handling of headers and request bodies
✅ Reduces boilerplate compared to HttpURLConnection
👉 With @Grab
and HTTPBuilder
, your Groovy scripts are shorter, cleaner, and easier to maintain.
9. Conclusion + Best Practices
In this tutorial, we explored multiple ways to perform HTTP requests in Groovy, starting from the standard HttpURLConnection
to more advanced and expressive approaches using Groovy’s built-in JsonSlurper
, JsonOutput
, and libraries such as HTTPBuilder
. Along the way, we demonstrated how to handle common tasks like parsing JSON responses, sending POST requests, adding headers and authentication, and dealing with response codes and errors.
Key Takeaways
-
Groovy + Java Interop: You can always fall back on Java’s
HttpURLConnection
if you need low-level control or wish to avoid extra dependencies. -
JsonSlurper & JsonOutput: These provide a straightforward way to parse incoming JSON and create JSON payloads when working with REST APIs.
-
HTTPBuilder/RESTClient: These libraries simplify boilerplate code, letting you focus on the API interaction rather than raw request/response handling.
Best Practices
-
Always Handle Errors Gracefully
Check response codes before processing the body. Implement retries or fallback logic if the API is not reliable. -
Use Timeouts
Set appropriate connection and read timeouts to prevent hanging requests. -
Secure Authentication
Store API keys, tokens, and credentials securely (e.g., environment variables or secrets manager). Avoid hardcoding them in source code. -
Prefer External Libraries for Complex APIs
WhileHttpURLConnection
works, libraries likeHTTPBuilder
or modern alternatives (OkHttp
,Apache HttpClient
) offer more readable and maintainable code. -
Log Requests and Responses
For debugging, logging API calls helps troubleshoot issues with payloads, headers, or authentication. -
Keep Dependencies in Check
If using@Grab
for dependencies, ensure compatibility with your Groovy version to avoid runtime errors likeNoClassDefFoundError
.
✅ With these tools and practices, you should be able to integrate Groovy seamlessly with any RESTful API, whether for quick scripts, backend services, or data pipelines.
You can find the source code used in this tutorial on our GitHub.
That's just the basics. If you need more deep learning about Groovy and Grails, you can take the following cheap course:
- The Complete Apache Groovy Developer Course
- Groovy Fundamentals For Testers - Step By Step
- Groovy Programming Fundamentals for Java Developers
- The Complete Jenkins DevOps CI/CD Pipeline Bootcamp
- WebServices/API Testing by SoapUI & ReadyAPI - Groovy |30+hr
- Mastering Grails. A Comprehensive Grails Course.
- Intro to web programming with Groovy on Grails
Thanks!