Skip to main content
Back to Blog
API Testing
2026-05-13

Robot Framework REST instance Library Complete Guide

Use the REST instance library for declarative API testing in Robot Framework. JSON Schema validation, OpenAPI compliance, contract testing, and CI patterns.

Robot Framework REST instance Library Complete Guide

REST instance is a declarative, contract-first API testing library for Robot Framework. While RequestsLibrary gives you imperative keywords - GET, POST, PUT - REST instance provides high-level instance-based syntax with built-in JSON Schema validation, response code matchers, header assertions, and OpenAPI/Swagger integration. The library was designed for teams who want to validate that their APIs conform to a contract rather than just inspect individual fields. Combined with OpenAPI specs, REST instance lets you catch breaking changes before they hit production.

This complete guide walks through REST instance from installation to advanced contract testing patterns. You'll learn how to define API instances with base URLs and headers, how to send requests and assert on responses, how to validate against JSON Schema, how to integrate with OpenAPI documents for full contract testing, and how to wire the whole thing into CI/CD. Real test suites and example schemas are included. By the end you'll be ready to enforce API contracts in every PR.

Key Takeaways

  • REST instance is a higher-level library than RequestsLibrary
  • Declarative instance syntax with persistent base URL and headers
  • Built-in JSON Schema validation
  • Integrates with OpenAPI 3 documents
  • Response chaining via output keyword
  • Built-in matchers for status codes, headers, JSON
  • Best for contract-first API testing

Installation

pip install robotframework-restinstance

Basic Usage

*** Settings ***
Library    REST    https://api.example.com

*** Test Cases ***
Get Single User
    GET    /users/1
    Integer    response status    200
    String    response body name
    String    response body email format=email

Three lines tell the library: status must be 200, name must be a string, email must be a string formatted as an email.

Instance Setup

*** Settings ***
Library    REST    https://api.example.com    timeout=30    headers={"X-API-Key": "secret"}

The first arg is the base URL. Subsequent args configure default request behavior.

GET, POST, PUT, DELETE

*** Test Cases ***
CRUD Flow
    POST    /users    {"name": "Alice", "email": "alice@example.com"}
    Integer    response status    201
    Integer    response body id
    ${id}=    Integer    response body id

    GET    /users/${id}
    Integer    response status    200
    String    response body name    Alice

    PUT    /users/${id}    {"name": "Alice Updated", "email": "alice@example.com"}
    Integer    response status    200

    DELETE    /users/${id}
    Integer    response status    204

Matchers

REST instance provides typed matchers:

MatcherPurposeExample
IntegerMatch integerInteger response status 200
NumberMatch numberNumber response body price 9.99
StringMatch stringString response body name Alice
BooleanMatch booleanBoolean response body active true
ArrayMatch arrayArray response body items minItems=1
ObjectMatch objectObject response body
NullMatch nullNull response body deleted_at

JSON Schema Validation

*** Test Cases ***
Validate Response Against Schema
    GET    /users/1
    Validate Response    schemas/user.json

The schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["id", "name", "email"],
  "properties": {
    "id": {"type": "integer"},
    "name": {"type": "string"},
    "email": {"type": "string", "format": "email"},
    "created_at": {"type": "string", "format": "date-time"}
  },
  "additionalProperties": false
}

Validate Response checks the entire response body. If a field violates the schema, the test fails with a precise message.

OpenAPI Integration

*** Settings ***
Library    REST    https://api.example.com    spec=openapi.yaml

When you provide an OpenAPI document, REST instance auto-validates every response against the documented schema. This catches drift between code and docs.

*** Test Cases ***
All Endpoints Match Spec
    GET    /users/1
    GET    /users
    POST    /users    {"name": "Test"}
    # No explicit validation needed - all auto-checked against openapi.yaml

Headers

*** Test Cases ***
Authenticated Request
    Set Headers    {"Authorization": "Bearer token-here"}
    GET    /me
    Integer    response status    200
    String    response body email

Or use the headers field per request:

GET    /me    headers={"Authorization": "Bearer token"}

Query Parameters

GET    /users    query={"limit": 10, "offset": 0, "sort": "name"}

Status Code Ranges

Integer    response status    200    # exactly 200
Integer    response status    2xx   # any 2xx
Integer    response status    4xx   # any client error

Response Chaining

*** Test Cases ***
Use Field From Previous Response
    POST    /orders    {"sku": "ABC", "quantity": 1}
    ${order_id}=    Output    response body id

    GET    /orders/${order_id}
    String    response body status    pending

Output extracts a field for later use.

Bulk Validation

*** Test Cases ***
List Endpoint Returns Valid Items
    GET    /users
    Integer    response status    200
    Array    response body    minItems=1    maxItems=100
    Validate Response    schemas/user_list.json

Files

*** Test Cases ***
Upload Avatar
    POST    /avatars    file=avatar.png
    Integer    response status    201

Authentication

*** Settings ***
Library    REST    https://api.example.com    headers={"Authorization": "Bearer %{TOKEN}"}

The %{} syntax reads from environment.

Error Cases

*** Test Cases ***
Missing User Returns 404
    GET    /users/999999
    Integer    response status    404
    String    response body code    USER_NOT_FOUND

Per Suite Setup

*** Settings ***
Library    REST    ${API_URL}
Suite Setup    Login And Set Token

*** Keywords ***
Login And Set Token
    POST    /auth/login    {"email": "test@example.com", "password": "secret"}
    ${token}=    Output    response body access_token
    Set Headers    {"Authorization": "Bearer ${token}"}

REST instance vs RequestsLibrary

AspectREST instanceRequestsLibrary
StyleDeclarativeImperative
Schema validationBuilt-inManual via plugin
OpenAPIBuilt-inManual
VerbosityConciseVerbose
Learning curveModerateEasy
Best forContract testingFree-form API testing

Contract Testing Pattern

*** Settings ***
Library    REST    ${API_URL}    spec=contracts/orders.yaml
Test Template    Contract Check

*** Test Cases ***
GET Single Order              GET    /orders/42                                  200
GET Missing Order             GET    /orders/999999                              404
POST Valid Order              POST   /orders    {"sku":"ABC","qty":1}            201
POST Invalid Order            POST   /orders    {"sku":"ABC"}                    400

*** Keywords ***
Contract Check
    [Arguments]    ${method}    ${path}    ${body}    ${expected}
    Run Keyword    ${method}    ${path}    ${body}
    Integer    response status    ${expected}

Data Driven Validation

*** Settings ***
Library    REST    ${API_URL}
Library    DataDriver    file=test_data/users.csv
Test Template    Validate User

*** Test Cases ***
User Schema Check    ${user_id}

*** Keywords ***
Validate User
    [Arguments]    ${user_id}
    GET    /users/${user_id}
    Integer    response status    200
    Validate Response    schemas/user.json

Snapshot Testing

*** Test Cases ***
Response Matches Snapshot
    GET    /reports/daily
    Save Response    snapshots/daily_report.json

On rerun, you can diff against the snapshot.

CI Integration

name: API Contract Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - run: pip install robotframework robotframework-restinstance
      - run: robot --outputdir results tests/contract/
        env:
          API_URL: ${{ secrets.STAGING_API_URL }}
          TOKEN: ${{ secrets.STAGING_TOKEN }}
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: results
          path: results/

Real Suite Example

*** Settings ***
Documentation    Orders API contract suite
Library          REST    ${API_URL}    spec=openapi.yaml    headers={"Authorization": "Bearer %{TOKEN}"}
Suite Setup      Setup Test Order
Suite Teardown   Cleanup Test Order

*** Variables ***
${API_URL}    https://api.shop.example.com

*** Test Cases ***
Get Order Returns Correct Schema
    [Tags]    contract    orders
    GET    /orders/${ORDER_ID}
    Integer    response status    200
    Validate Response    schemas/order.json

List Orders Endpoint Paginated
    [Tags]    contract    orders
    GET    /orders    query={"limit": 10, "offset": 0}
    Integer    response status    200
    Array    response body items    minItems=0    maxItems=10
    Integer    response body total

Cancel Order Returns 204
    [Tags]    contract    orders
    DELETE    /orders/${ORDER_ID}
    Integer    response status    204

Cancelled Order Returns Cancelled Status
    [Tags]    contract    orders
    GET    /orders/${ORDER_ID}
    String    response body status    cancelled

*** Keywords ***
Setup Test Order
    POST    /orders    {"sku": "TEST-SKU", "quantity": 1}
    ${id}=    Output    response body id
    Set Suite Variable    ${ORDER_ID}    ${id}

Cleanup Test Order
    DELETE    /orders/${ORDER_ID}

Anti-Patterns

Anti-PatternBetter
No schema validationValidate every response
Hardcoded URLsPer-env config
Skipping 4xx testsTest error contracts too
One mega testSplit by endpoint
Embedded credsEnv vars

Debugging

When validation fails:

*** Test Cases ***
Debug Response
    GET    /users/1
    Log    ${RESPONSE}    INFO
    Output    response    debug.json

The Output keyword to a file gives you the full response for analysis.

Conclusion

REST instance is a great choice for API testing when your priority is contract enforcement. The declarative style produces concise tests, JSON Schema and OpenAPI integration catches drift early, and the built-in matchers cover most assertion needs. Pair it with RequestsLibrary for flows that need imperative control, and you have full coverage of API testing scenarios in Robot Framework.

Start by writing schemas for your most important endpoints. Add a REST instance suite that validates each one. As soon as a backend change breaks a schema, the suite fails - and you've caught a regression before deployment. Visit the skills directory or read the API contract testing guide for related patterns.

Robot Framework REST instance Library Complete Guide | QASkills.sh