OpenTestData API

REST API behind opentestdata.org, test.ai's free and open database of automated test fixture data. 13 paths / 16 operations covering user signup and login, e-mail confirmation, avatars, admin promotion, test and datum create/read/update, and a combined search over tests and data. Authenticated with a JWT bearer token. The publicly hosted instance the provider documented, api.opentestdata.org, no longer resolves; the contract survives in the company's own repository.

Operations 16

GET /ping server responds with PONG #
POST /users Create a new user #
POST /users/login Log in and retrieve an access token #
POST /users/resend_confirmation_email Re-send the confirmation e-mail to the address associated with the logged in user #
GET /users/confirm_email/{token} Confirm an e-mail address #
GET /users/{id} Get details of a user #
POST /users/{id} Update details for a user #
GET /users/{id}/avatar Get avatar image data (this API is only available in the development version of the server) #
POST /users/{id}/avatar Upload image data to be used as the user avatar #
POST /users/{id}/promote Promote a user to an admin (admin authorization required) #
POST /data Create a new test datum #
GET /data/{id} Get details of a datum #
POST /data/{id} Update a test datum #
POST /tests Create a new test #
GET /tests/{id} Get details of a test #
POST /search Search for tests and data #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/opentestdata-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no email required.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

test-ai-opentestdata-openapi.yaml Raw ↑
# generated: '2026-08-30'
# method: derived
# source: openapi/_original/opentestdata/api.yaml (verbatim fragments harvested from
#   https://github.com/testdotai/opentestdata-api/tree/master/api/openapi — test.ai's own GitHub org)
# note: The provider publishes this contract as six connexion-style fragment files with relative
#   $refs, which is not a loadable single OpenAPI document. This file is a mechanical bundle of
#   those fragments — $refs resolved into components, nothing added, removed or reworded.
#   No servers[] block is asserted: the hosted instance (api.opentestdata.org) no longer resolves.
openapi: 3.0.0
info:
  version: 1.0.0
  title: OpenTestData
  license:
    name: MIT
paths:
  /ping:
    get:
      summary: server responds with PONG
      operationId: api.handlers.general.ping
      responses:
        '200':
          $ref: '#/components/responses/Base_PingSuccess'
  /users:
    post:
      summary: Create a new user
      operationId: api.handlers.users.signup
      requestBody:
        $ref: '#/components/requestBodies/Users_SignUp'
      responses:
        '200':
          $ref: '#/components/responses/Users_SignUpSuccess'
        '500':
          $ref: '#/components/responses/Users_SignUpError'
  /users/login:
    post:
      summary: Log in and retrieve an access token
      operationId: api.handlers.auth.login
      requestBody:
        $ref: '#/components/requestBodies/Users_Login'
      responses:
        '200':
          $ref: '#/components/responses/Users_LoginSuccess'
        '500':
          $ref: '#/components/responses/Base_Error'
  /users/resend_confirmation_email:
    post:
      summary: Re-send the confirmation e-mail to the address associated with the logged in user
      operationId: api.handlers.users.resend_confirmation
      requestBody:
        $ref: '#/components/requestBodies/Users_EmailResend'
      responses:
        '200':
          $ref: '#/components/responses/Users_EmailResendSuccess'
        '500':
          $ref: '#/components/responses/Base_Error'
      security:
      - jwt: []
  /users/confirm_email/{token}:
    get:
      summary: Confirm an e-mail address
      operationId: api.handlers.users.confirm_email
      parameters:
      - in: path
        name: token
        required: true
        schema:
          type: string
        description: The e-mail confirmation token
      responses:
        '200':
          $ref: '#/components/responses/Users_EmailConfirmSuccess'
        '500':
          $ref: '#/components/responses/Base_Error'
  /users/{id}:
    get:
      summary: Get details of a user
      operationId: api.handlers.users.detail
      parameters:
      - in: path
        name: id
        required: true
        schema:
          type: integer
          minimum: 1
        description: The user ID
      responses:
        '200':
          $ref: '#/components/responses/Users_GetUserSuccess'
        '500':
          $ref: '#/components/responses/Base_Error'
      security:
      - jwt: []
    post:
      summary: Update details for a user
      operationId: api.handlers.users.update
      parameters:
      - in: path
        name: id
        required: true
        schema:
          type: integer
          minimum: 1
        description: The user ID
      requestBody:
        $ref: '#/components/requestBodies/Users_UpdateUser'
      responses:
        '200':
          $ref: '#/components/responses/Users_UserDetails'
        '500':
          $ref: '#/components/responses/Base_Error'
      security:
      - jwt: []
  /users/{id}/avatar:
    get:
      summary: Get avatar image data (this API is only available in the development version of the server)
      operationId: api.handlers.users.get_avatar
      parameters:
      - in: path
        name: id
        required: true
        schema:
          type: integer
          minimum: 1
        description: The user ID
      responses:
        '200':
          $ref: '#/components/responses/Users_Avatar'
        '500':
          $ref: '#/components/responses/Base_Error'
    post:
      summary: Upload image data to be used as the user avatar
      operationId: api.handlers.users.upload_avatar
      parameters:
      - in: path
        name: id
        required: true
        schema:
          type: integer
          minimum: 1
        description: The user ID
      requestBody:
        $ref: '#/components/requestBodies/Users_UpdateAvatar'
      responses:
        '200':
          $ref: '#/components/responses/Users_UpdateAvatar'
        '500':
          $ref: '#/components/responses/Base_Error'
      security:
      - jwt: []
  /users/{id}/promote:
    post:
      summary: Promote a user to an admin (admin authorization required)
      operationId: api.handlers.users.promote
      parameters:
      - in: path
        name: id
        required: true
        schema:
          type: integer
          minimum: 1
        description: The user ID
      responses:
        '200':
          $ref: '#/components/responses/Users_UserDetails'
        '500':
          $ref: '#/components/responses/Base_Error'
      security:
      - jwt: []
  /data:
    post:
      summary: Create a new test datum
      operationId: api.handlers.data.create
      requestBody:
        $ref: '#/components/requestBodies/Data_DatumDetails'
      responses:
        '200':
          $ref: '#/components/responses/Data_Datum'
        '500':
          $ref: '#/components/responses/Base_Error'
      security:
      - jwt: []
  /data/{id}:
    get:
      summary: Get details of a datum
      parameters:
      - in: path
        name: id
        required: true
        schema:
          type: integer
          minimum: 1
        description: The datum ID
      operationId: api.handlers.data.detail
      responses:
        '200':
          $ref: '#/components/responses/Data_Datum'
        '500':
          $ref: '#/components/responses/Base_Error'
      security:
      - jwt: []
    post:
      summary: Update a test datum
      operationId: api.handlers.data.update
      parameters:
      - in: path
        name: id
        required: true
        schema:
          type: integer
          minimum: 1
        description: The datum ID
      requestBody:
        $ref: '#/components/requestBodies/Data_DatumDetails'
      responses:
        '200':
          $ref: '#/components/responses/Data_Datum'
        '500':
          $ref: '#/components/responses/Data_DatumUpdateError'
      security:
      - jwt: []
  /tests:
    post:
      summary: Create a new test
      operationId: api.handlers.tests.create
      requestBody:
        $ref: '#/components/requestBodies/Tests_TestDetails'
      responses:
        '200':
          $ref: '#/components/responses/Tests_TestDetails'
        '500':
          $ref: '#/components/responses/Base_Error'
      security:
      - jwt: []
  /tests/{id}:
    get:
      summary: Get details of a test
      parameters:
      - in: path
        name: id
        required: true
        schema:
          type: integer
          minimum: 1
        description: The test ID
      operationId: api.handlers.tests.detail
      responses:
        '200':
          $ref: '#/components/responses/Tests_TestDetails'
        '500':
          $ref: '#/components/responses/Base_Error'
      security:
      - jwt: []
  /search:
    post:
      summary: Search for tests and data
      operationId: api.handlers.search.search
      requestBody:
        $ref: '#/components/requestBodies/Search_Search'
      responses:
        '200':
          $ref: '#/components/responses/Search_SearchResults'
      security:
      - jwt: []
components:
  schemas:
    Base_Base:
      properties:
        id:
          type: integer
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    Data_DatumBase:
      properties:
        name:
          type: string
          maxLength: 100
          minLength: 1
        type:
          type: string
          enum:
          - 'NULL'
          - BOOL
          - NUM
          - STR
          - OBJ
        value:
          type: string
          maxLength: 1024
      required:
      - name
      - type
      - value
      additionalProperties: false
    Data_Datum:
      allOf:
      - $ref: '#/components/schemas/Data_DatumBase'
      - $ref: '#/components/schemas/Base_Base'
      - properties:
          user_id:
            type: integer
    Search_SearchQuery:
      properties:
        type:
          type: string
          enum:
          - ALL
          - TESTS
          - DATA
        query:
          type: string
          minLength: 2
    Search_SearchResults:
      properties:
        tests:
          type: array
          items:
            $ref: '#/components/schemas/Tests_Test'
        data:
          type: array
          items:
            $ref: '#/components/schemas/Data_Datum'
    Tests_TestBase:
      properties:
        name:
          type: string
          maxLength: 160
          minLength: 1
        data:
          type: array
          items:
            $ref: '#/components/schemas/Tests_TestData'
      required:
      - name
      - data
      additionalProperties: false
    Tests_Test:
      allOf:
      - $ref: '#/components/schemas/Tests_TestBase'
      - $ref: '#/components/schemas/Base_Base'
      - properties:
          user_id:
            type: integer
    Tests_TestData:
      properties:
        label:
          type: string
          maxLength: 80
          minLength: 1
        disposition:
          type: string
          enum:
          - NEUTRAL
          - POS
          - NEG
          - EDGE
          - DESTRUCTIVE
        datum_id:
          type: integer
    Users_SignUp:
      properties:
        username:
          type: string
          maxLength: 80
          minLength: 1
        email:
          type: string
          maxLength: 120
          minLength: 5
        password:
          type: string
          minLength: 8
        bio:
          type: string
          maxLength: 240
        email_confirmation_url:
          type: string
      required:
      - username
      - email
      - password
      - bio
      - email_confirmation_url
      additionalProperties: false
    Users_Login:
      properties:
        username:
          type: string
        password:
          type: string
      required:
      - username
      - password
      additionalProperties: false
    Users_User:
      allOf:
      - $ref: '#/components/schemas/Base_Base'
      - properties:
          username:
            type: string
            maxLength: 80
            minLength: 1
          avatar_url:
            type: string
          bio:
            type: string
          data:
            type: array
            items:
              $ref: '#/components/schemas/Data_Datum'
    Users_EmailResend:
      properties:
        email_confirmation_url:
          type: string
      required:
      - email_confirmation_url
      additionalProperties: false
    Users_UpdateUser:
      properties:
        email:
          type: string
          maxLength: 120
          minLength: 5
        password:
          type: string
          minLength: 8
      additionalProperties: false
  responses:
    Base_PingSuccess:
      description: Successful ping
      content:
        application/json:
          schema:
            type: string
    Base_Error:
      description: Error
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
    Data_Datum:
      description: Datum details
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Data_Datum'
    Data_DatumUpdateError:
      description: Datum Update Error
      content:
        application/json:
          schema:
            type: object
            properties:
              datum_id:
                type: number
              error:
                type: string
    Search_SearchResults:
      description: Search results
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Search_SearchResults'
    Tests_TestDetails:
      description: Test details
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Tests_Test'
    Users_SignUpSuccess:
      description: New User
      content:
        application/json:
          schema:
            type: object
            $ref: '#/components/schemas/Users_User'
    Users_SignUpError:
      description: New User Error
      content:
        application/json:
          schema:
            type: object
            properties:
              username:
                type: string
              email:
                type: string
              error:
                type: string
    Users_LoginSuccess:
      description: Auth token
      content:
        application/json:
          schema:
            properties:
              token:
                type: string
              user_id:
                type: integer
    Users_EmailResendSuccess:
      description: Successful resend
      content:
        application/json:
          schema:
            properties:
              success:
                type: boolean
    Users_EmailConfirmSuccess:
      description: Auth token
      content:
        application/json:
          schema:
            properties:
              confirmed:
                type: boolean
    Users_GetUserSuccess:
      description: User details
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Users_User'
    Users_UserDetails:
      description: User details
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Users_User'
    Users_Avatar:
      description: The raw avatar image data
      content:
        image/jpeg:
          schema:
            type: string
            format: binary
    Users_UpdateAvatar:
      description: The URL for the newly-uploaded image
      content:
        application/json:
          schema:
            type: string
  requestBodies:
    Data_DatumDetails:
      description: Datum details
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Data_DatumBase'
    Search_Search:
      description: Search parameters
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Search_SearchQuery'
    Tests_TestDetails:
      description: Test details
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Tests_TestBase'
    Users_SignUp:
      description: Data needed to create a new User
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Users_SignUp'
    Users_Login:
      description: Login details
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Users_Login'
    Users_EmailResend:
      description: Confirmation url to include in the confirmation e-mail
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Users_EmailResend'
    Users_UpdateUser:
      description: User details
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Users_UpdateUser'
    Users_UpdateAvatar:
      description: Image mime type and data
      required: true
      content:
        application/json:
          schema:
            properties:
              type:
                type: string
              data:
                type: string
  securitySchemes:
    jwt:
      type: http
      scheme: bearer
      bearerFormat: JWT
      x-bearerInfoFunc: api.handlers.auth.check_token