API

WebSocket

REST gives you the final output. A WebSocket connection gives you output as it appears, and lets your user answer a program while it runs.

Use it for a terminal, a program that prompts the user, or anything where waiting until the end is not good enough.

Everything about languages, versions and program parameters is the same as REST. What changes is how you connect and how messages arrive.

How the connection is made

Your server holds the secret. The browser holds only a token, and talks to us directly.

WebSocket call flowYour server exchanges the client secret for a token, gives the token to the browser, and the browser then connects to JDoodle directly to run programs and send input.Your pageYour serverJDoodle1. Client ID and secretPOST /v1/auth-token2. A token, valid 3 minutes3. The token onlynever the secret4. Connect with the token/v1/stomp5. Program and input, output back
Steps 1 to 3 happen on your server. Steps 4 and 5 run directly between the browser and us, while the program runs.

Your server is only involved in getting the token. After that the conversation is between your user and us, which is what makes an interactive program feel immediate.

Get a token

The browser connects to us directly, so your client secret must not be involved. Your server exchanges the secret for a short-lived token first.

curl -X POST 'https://api.jdoodle.com/v1/auth-token' \
  -H 'Content-Type: application/json' \
  -d '{
        "clientId": "your_client_id",
        "clientSecret": "your_client_secret"
      }'
// Java 11 or newer. Runs on your server, never in a browser.
String body = "{"
    + "\"clientId\": \"your_client_id\","
    + "\"clientSecret\": \"your_client_secret\""
    + "}";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.jdoodle.com/v1/auth-token"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<String> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());

System.out.println(response.body());
// Node 18 or newer. Runs on your server, never in a browser.
const response = await fetch('https://api.jdoodle.com/v1/auth-token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    clientId: 'your_client_id',
    clientSecret: 'your_client_secret'
  })
})

const { token } = await response.json()
// Send this token to the browser. Never the secret.
# Runs on your server, never in a browser.
import requests

response = requests.post(
    "https://api.jdoodle.com/v1/auth-token",
    json={
        "clientId": "your_client_id",
        "clientSecret": "your_client_secret",
    },
)

token = response.json()["token"]
{ "token": "your_generated_token" }

The token lasts three minutes, and you can run as many programs as you like in that time. Getting one costs one credit, on top of the credit each run costs, so one token covering a whole session is cheaper than one per run. See credits and pricing.

Request a token when a user is about to run something, rather than fetching one and keeping it.

Connect

https://api.jdoodle.com/v1/stomp

The connection speaks STOMP over SockJS, so use a SockJS client with a STOMP wrapper rather than a raw WebSocket.

The examples below are JavaScript because this half runs in your user's browser. Your server's part is getting the token above, which you can do in any language.

What Where
Subscribe to /user/queue/execute-i
Send messages to /app/execute-ws-api-token
// sockjs-client and webstomp-client, loaded in the browser
const client = webstomp.over(new SockJS('https://api.jdoodle.com/v1/stomp'))

client.connect({}, () => {
  client.subscribe('/user/queue/execute-i', (message) => {
    const status = Number(message.headers.statusCode)
    if (status === 201) console.log('started')
    else if (status === 204) console.log('finished')
    else console.log(message.body)
  })

  client.send(
    '/app/execute-ws-api-token',
    JSON.stringify({
      script: 'print("Hello, World!")',
      language: 'python3',
      versionIndex: '0'
    }),
    { message_type: 'execute', token }
  )
})

Every message carries two headers:

  • token. The token your server obtained.
  • message_type. Either execute to start a program, or input to answer one that is running.

Start a program

Send a message_type of execute, with the same fields REST takes:

{
  "script": "name = input()\nprint(f\"Hello, {name}\")",
  "language": "python3",
  "versionIndex": "0"
}

Answer a running program

Send a message_type of input with what your user typed. The body is the text itself rather than JSON, and a newline is \n.

client.send('/app/execute-ws-api-token', userTyped + '\n', {
  message_type: 'input',
  token
})

This is the part REST cannot do. You do not need to know the input before the program starts.

What comes back

Output arrives as messages on the queue you subscribed to. The status on each message says what it is:

Status Meaning
201 Execution started
204 Execution time
206 Output files
400, 401 Authentication problem
429 Daily limit reached
410, 500 Server error

A working sample

A complete HTML page that connects, runs a program, and lets you answer it while it runs. Save it, open it in a browser, paste a token, and press Run.

Download jdoodle-websocket.html

It is one file with no build step. The two libraries load from a CDN, and the whole flow is about eighty lines, so it is easier to read than to describe.

When REST is the better choice

REST is less to build and less to get wrong. Choose the socket only when your users need to interact with a running program, or when output arrives over time and they should see it as it happens.

What next

Whichever interface you use, the language and version values are the same.

This website uses cookies to ensure you get the best experience on our website.