Skip to content
Now Hiring

Cloud, data, Salesforce, SAP, engineering and more roles. View open jobs.

An engineer's workstation seen from above
A keyboard and mouse at a security analyst's desk
Base URL
https://oceanbluecorp.com/api/v1
Auth
API key in the X-API-Key header
Version
v1

Job Feed API

Pull our live job listings into your platform. A versioned REST API that returns JSON, authenticated with an API key.

01Overview

The Oceanblue Solutions, Inc. Job Feed API lets external platforms pull our live job listings. It is a versioned REST API hosted at /api/v1, and every request and response is JSON.

bash
curl https://oceanbluecorp.com/api/v1/jobs \
  -H "X-API-Key: obk_live_your_key_here"

02Authentication

Every request must include your API key in the X-API-Key header. For a quick test you can pass it as the ?api_key= query parameter instead.

Keep your API key secret. Do not put it in client-side code or a public repository. Contact us straight away if a key is compromised and we will disable it.

bash
# Recommended: header
curl https://oceanbluecorp.com/api/v1/jobs \
  -H "X-API-Key: obk_live_your_api_key_here"

# Alternative: query parameter (testing only)
curl "https://oceanbluecorp.com/api/v1/jobs?api_key=obk_live_your_api_key_here"
StatusErrorMeaning
401Missing API key. Pass X-API-Key header.No key was sent
401Invalid API key.The key is not in our system
403API key is disabled.The key has been revoked or disabled
403This API key does not have the "<scope>" scope.The key lacks the scope this endpoint needs

Scopes

Each key is issued at one of two access levels. A read-only key that calls a write endpoint gets a 403 naming the scope it is missing, in a requiredScope field. Ask your Oceanblue contact if you need a level changed; the key value itself does not change.

Access levelScopesEndpoints
View jobsjobs:readGET /api/v1/jobs, GET /api/v1/jobs/:id
Create and view jobsjobs:read, jobs:writeAll of the above, plus POST /api/v1/jobs

03Endpoints

GET/api/v1/jobs

Returns a paginated list of job listings, newest first. Without a status filter it returns only active and open jobs.

Parameters

NameTypeRequiredDescription
statusstringOptionalactive, open, paused or closed. Any other value is ignored
departmentstringOptionalExact department name, case-insensitive
typestringOptionalEmployment type, see Filtering and pagination
pageintegerOptionalPage number (default 1)
limitintegerOptionalResults per page, 1 to 100 (default 20)

Example response

json
{
  "data": [
    {
      "id": "b3f1a2c4-...",
      "postingId": "OB-2025-0042",
      "title": "Senior SAP Consultant",
      "department": "SAP Practice",
      "location": "Columbus, OH",
      "state": "OH",
      "type": "contract",
      "workplace": "hybrid",
      "description": "<p>We are seeking...</p>",
      "requirements": "<ul><li>5+ years SAP experience</li></ul>",
      "responsibilities": "<ul><li>Lead implementation</li></ul>",
      "status": "active",
      "submissionDueDate": "2025-06-15T00:00:00.000Z",
      "postedByName": "Jane Doe",
      "createdAt": "2025-05-01T14:22:00.000Z"
    }
  ],
  "meta": {
    "total": 38,
    "page": 1,
    "limit": 20,
    "totalPages": 2,
    "hasNextPage": true,
    "hasPrevPage": false
  }
}

GET/api/v1/jobs/:id

Returns a single job by its UUID, whatever its status.

Parameters

NameTypeRequiredDescription
idstringRequiredJob UUID, from the id field in list results

Example response

json
{
  "data": {
    "id": "b3f1a2c4-...",
    "postingId": "OB-2025-0042",
    "title": "Senior SAP Consultant",
    "department": "SAP Practice",
    "location": "Columbus, OH",
    "state": "OH",
    "type": "contract",
    "description": "<p>We are seeking a Senior SAP Consultant...</p>",
    "requirements": "<ul><li>5+ years SAP experience</li></ul>",
    "responsibilities": "<ul><li>Lead full-cycle implementation</li></ul>",
    "salary": { "min": 80, "max": 110, "currency": "USD" },
    "status": "active",
    "submissionDueDate": "2025-06-15T00:00:00.000Z",
    "postedByName": "Jane Doe",
    "createdAt": "2025-05-01T14:22:00.000Z",
    "updatedAt": "2025-05-02T09:10:00.000Z"
  }
}

POST/api/v1/jobs

Files a new job posting. Needs a key with the jobs:write scope. Fields not listed here are ignored.

Parameters

NameTypeRequiredDescription
titlestringRequiredJob title, up to 200 characters
departmentstringRequiredBusiness unit or practice area, up to 120 characters
typestringRequiredfull-time, part-time, contract, contract-to-hire, direct-hire or managed-teams
descriptionstringRequiredJob description. Basic HTML is accepted and sanitized on save
locationstringOptionalCity and state, e.g. Columbus, OH. Required unless workplace is remote
workplacestringOptionalon-site, hybrid or remote
statestringOptionalTwo-letter state code
requirementsstringOptionalRequirements, as HTML or plain text
responsibilitiesstringOptionalResponsibilities, as HTML or plain text
salaryobjectOptional{ min, max, currency }. Dropped unless min and max are both numbers and max is at least min
statusstringOptionaldraft (default), active or open. Anything else is rejected
submissionDueDatestringOptionalISO 8601 application deadline

Example response

json
// 201 Created
{
  "data": {
    "id": "9c2e77a1-...",
    "postingId": "OB-2025-0043",
    "title": "Senior SAP Consultant",
    "department": "SAP Practice",
    "location": "Columbus, OH",
    "type": "contract",
    "status": "draft",
    "postedByName": "Your API key's name",
    "createdAt": "2025-05-04T11:02:00.000Z"
  }
}

// 403 when the key is read-only
{
  "error": "This API key does not have the \"jobs:write\" scope.",
  "requiredScope": "jobs:write"
}

Postings created over the API arrive as draft unless you send status, so a recruiter reviews them before they reach the public jobs page. Rates, client and vendor details and recruiter assignments cannot be set through this endpoint. A type of remote is still accepted from older integrations and is saved as full-time with a remote workplace.

04Filtering and pagination

By default the list endpoint returns only active and open jobs. Query parameters can be combined.

bash
# Active contract jobs, page 2
GET /api/v1/jobs?type=contract&status=active&page=2&limit=10

# Open jobs in the "SAP Practice" department
GET /api/v1/jobs?department=SAP+Practice&status=open

# One job by ID
GET /api/v1/jobs/b3f1a2c4-1234-5678-abcd-ef0123456789
ParameterValues
statusactive · open · paused · closed
typefull-time · part-time · contract · contract-to-hire · direct-hire · managed-teams
limitInteger 1 to 100. Default 20.

05Response schema

Job objects contain these fields. Fields with no value are left out of the JSON. Pay rates, bill rates, recruiter assignments and other internal fields are never included.

FieldTypeNotes
idstringUUID. Use it with /api/v1/jobs/:id
postingIdstringHuman-readable ID, e.g. OB-2025-0042
titlestringJob title
departmentstringBusiness unit or practice area
locationstringCity and state, e.g. Columbus, OH. Empty for a remote role with no base
workplacestringon-site, hybrid or remote. Absent on older postings
statestringTwo-letter state code
typestringEmployment type. Older postings may still read remote
descriptionstringFull job description, as HTML
requirementsstring | string[]HTML on current postings; an array of bullet points on older ones
responsibilitiesstring | string[]HTML on current postings; an array of bullet points on older ones
salaryobject{ min, max, currency, period? }, only when the posting publishes its pay. No period means annual
skillsstring[]Skills the role asks for. Absent on older postings
statusstringactive, open, paused, closed, on-hold or draft
submissionDueDatestringISO 8601 application deadline
clientNamestringEnd-client company name, when disclosed
vendorNamestringStaffing vendor name, when applicable
postedByNamestringWho posted it: a recruiter, or the API key's name
createdAtstringISO 8601 creation time
updatedAtstringISO 8601 last update

06Errors

Every error returns a JSON body with an error field.

json
{
  "error": "Missing API key. Pass X-API-Key header."
}
HTTP codeMeaningWhat to do
400The POST body failed validationRead the error message, which names the field
401Missing or invalid API keyCheck that X-API-Key is set and correct
403Key disabled, or missing a scopeContact us; the key may be revoked or read-only
404Job not foundThe job ID does not exist or was removed
500Server errorRetry after a moment; contact us if it persists

07Quickstart

Examples to copy and run.

cURL

bash
curl https://oceanbluecorp.com/api/v1/jobs \
  -H "X-API-Key: obk_live_your_key_here" | jq .

JavaScript / TypeScript

typescript
const BASE = "https://oceanbluecorp.com/api/v1";
const KEY  = process.env.OCEAN_BLUE_API_KEY;

async function getJobs(page = 1) {
  const res = await fetch(`${BASE}/jobs?page=${page}&limit=20`, {
    headers: { "X-API-Key": KEY! },
  });
  if (!res.ok) throw new Error(`API error ${res.status}`);
  return res.json(); // { data: Job[], meta: { total, page, ... } }
}

async function getJob(id: string) {
  const res = await fetch(`${BASE}/jobs/${id}`, {
    headers: { "X-API-Key": KEY! },
  });
  if (!res.ok) throw new Error(`API error ${res.status}`);
  return res.json(); // { data: Job }
}

Python

python
import os, requests

BASE = "https://oceanbluecorp.com/api/v1"
HEADERS = {"X-API-Key": os.environ["OCEAN_BLUE_API_KEY"]}

def get_jobs(page=1, limit=20):
    r = requests.get(f"{BASE}/jobs", headers=HEADERS,
                     params={"page": page, "limit": limit})
    r.raise_for_status()
    return r.json()  # {"data": [...], "meta": {...}}

def get_job(job_id: str):
    r = requests.get(f"{BASE}/jobs/{job_id}", headers=HEADERS)
    r.raise_for_status()
    return r.json()  # {"data": {...}}

08Get access

API access is available to vetted job platforms and technology partners. Email our team and we will issue you an API key within one business day.

Building on
our job feed?

Tell us about your platform and we will set up the right access level for it.