curl --request POST \
--url https://api.usecobalt.com/v1/services \
--header 'Content-Type: application/json' \
--header 'access_token: <api-key>' \
--header 'client_id: <api-key>' \
--header 'client_secret: <api-key>' \
--data '
{
"patient_mrn": "15539",
"team": "TestClinic",
"service_type": "GAD-7",
"form_id": "392",
"answers": {
"453149": "3",
"453150": "2",
"453156": "Very difficult"
},
"service_date": "2026-08-26",
"callback_urls": [
"<string>"
]
}
'import requests
url = "https://api.usecobalt.com/v1/services"
payload = {
"patient_mrn": "15539",
"team": "TestClinic",
"service_type": "GAD-7",
"form_id": "392",
"answers": {
"453149": "3",
"453150": "2",
"453156": "Very difficult"
},
"service_date": "2026-08-26",
"callback_urls": ["<string>"]
}
headers = {
"client_id": "<api-key>",
"client_secret": "<api-key>",
"access_token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
client_id: '<api-key>',
client_secret: '<api-key>',
access_token: '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
patient_mrn: '15539',
team: 'TestClinic',
service_type: 'GAD-7',
form_id: '392',
answers: {'453149': '3', '453150': '2', '453156': 'Very difficult'},
service_date: '2026-08-26',
callback_urls: ['<string>']
})
};
fetch('https://api.usecobalt.com/v1/services', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.usecobalt.com/v1/services",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'patient_mrn' => '15539',
'team' => 'TestClinic',
'service_type' => 'GAD-7',
'form_id' => '392',
'answers' => [
'453149' => '3',
'453150' => '2',
'453156' => 'Very difficult'
],
'service_date' => '2026-08-26',
'callback_urls' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"access_token: <api-key>",
"client_id: <api-key>",
"client_secret: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.usecobalt.com/v1/services"
payload := strings.NewReader("{\n \"patient_mrn\": \"15539\",\n \"team\": \"TestClinic\",\n \"service_type\": \"GAD-7\",\n \"form_id\": \"392\",\n \"answers\": {\n \"453149\": \"3\",\n \"453150\": \"2\",\n \"453156\": \"Very difficult\"\n },\n \"service_date\": \"2026-08-26\",\n \"callback_urls\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("client_id", "<api-key>")
req.Header.Add("client_secret", "<api-key>")
req.Header.Add("access_token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.usecobalt.com/v1/services")
.header("client_id", "<api-key>")
.header("client_secret", "<api-key>")
.header("access_token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"patient_mrn\": \"15539\",\n \"team\": \"TestClinic\",\n \"service_type\": \"GAD-7\",\n \"form_id\": \"392\",\n \"answers\": {\n \"453149\": \"3\",\n \"453150\": \"2\",\n \"453156\": \"Very difficult\"\n },\n \"service_date\": \"2026-08-26\",\n \"callback_urls\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usecobalt.com/v1/services")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["client_id"] = '<api-key>'
request["client_secret"] = '<api-key>'
request["access_token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"patient_mrn\": \"15539\",\n \"team\": \"TestClinic\",\n \"service_type\": \"GAD-7\",\n \"form_id\": \"392\",\n \"answers\": {\n \"453149\": \"3\",\n \"453150\": \"2\",\n \"453156\": \"Very difficult\"\n },\n \"service_date\": \"2026-08-26\",\n \"callback_urls\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "<string>",
"service_id": "<string>",
"job_id": 123
}{
"success": false,
"message": "<string>"
}{
"success": false,
"message": "<string>"
}{
"success": false,
"message": "<string>"
}Create Service
Queues a service (an episode visit with form documentation) for creation in the provider’s EMR system.
curl --request POST \
--url https://api.usecobalt.com/v1/services \
--header 'Content-Type: application/json' \
--header 'access_token: <api-key>' \
--header 'client_id: <api-key>' \
--header 'client_secret: <api-key>' \
--data '
{
"patient_mrn": "15539",
"team": "TestClinic",
"service_type": "GAD-7",
"form_id": "392",
"answers": {
"453149": "3",
"453150": "2",
"453156": "Very difficult"
},
"service_date": "2026-08-26",
"callback_urls": [
"<string>"
]
}
'import requests
url = "https://api.usecobalt.com/v1/services"
payload = {
"patient_mrn": "15539",
"team": "TestClinic",
"service_type": "GAD-7",
"form_id": "392",
"answers": {
"453149": "3",
"453150": "2",
"453156": "Very difficult"
},
"service_date": "2026-08-26",
"callback_urls": ["<string>"]
}
headers = {
"client_id": "<api-key>",
"client_secret": "<api-key>",
"access_token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
client_id: '<api-key>',
client_secret: '<api-key>',
access_token: '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
patient_mrn: '15539',
team: 'TestClinic',
service_type: 'GAD-7',
form_id: '392',
answers: {'453149': '3', '453150': '2', '453156': 'Very difficult'},
service_date: '2026-08-26',
callback_urls: ['<string>']
})
};
fetch('https://api.usecobalt.com/v1/services', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.usecobalt.com/v1/services",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'patient_mrn' => '15539',
'team' => 'TestClinic',
'service_type' => 'GAD-7',
'form_id' => '392',
'answers' => [
'453149' => '3',
'453150' => '2',
'453156' => 'Very difficult'
],
'service_date' => '2026-08-26',
'callback_urls' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"access_token: <api-key>",
"client_id: <api-key>",
"client_secret: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.usecobalt.com/v1/services"
payload := strings.NewReader("{\n \"patient_mrn\": \"15539\",\n \"team\": \"TestClinic\",\n \"service_type\": \"GAD-7\",\n \"form_id\": \"392\",\n \"answers\": {\n \"453149\": \"3\",\n \"453150\": \"2\",\n \"453156\": \"Very difficult\"\n },\n \"service_date\": \"2026-08-26\",\n \"callback_urls\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("client_id", "<api-key>")
req.Header.Add("client_secret", "<api-key>")
req.Header.Add("access_token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.usecobalt.com/v1/services")
.header("client_id", "<api-key>")
.header("client_secret", "<api-key>")
.header("access_token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"patient_mrn\": \"15539\",\n \"team\": \"TestClinic\",\n \"service_type\": \"GAD-7\",\n \"form_id\": \"392\",\n \"answers\": {\n \"453149\": \"3\",\n \"453150\": \"2\",\n \"453156\": \"Very difficult\"\n },\n \"service_date\": \"2026-08-26\",\n \"callback_urls\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usecobalt.com/v1/services")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["client_id"] = '<api-key>'
request["client_secret"] = '<api-key>'
request["access_token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"patient_mrn\": \"15539\",\n \"team\": \"TestClinic\",\n \"service_type\": \"GAD-7\",\n \"form_id\": \"392\",\n \"answers\": {\n \"453149\": \"3\",\n \"453150\": \"2\",\n \"453156\": \"Very difficult\"\n },\n \"service_date\": \"2026-08-26\",\n \"callback_urls\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "<string>",
"service_id": "<string>",
"job_id": 123
}{
"success": false,
"message": "<string>"
}{
"success": false,
"message": "<string>"
}{
"success": false,
"message": "<string>"
}/services call you can display a Processing status to your user, and when you receive the webhook notification you can update that to Completed.
How a service is created
Processing a service runs an ordered chain against the EMR:- Team to episode — the patient is assigned to the given
team. If the assignment opens a new episode, the service is written to it. If the patient is already on the team, the service is written to their most recent episode. - Service type — the
service_typeis resolved against the client’s live billing matrix. A service type that is not billable for the client fails the service (see Failure). - Form documentation — the
answersyou supply are validated against the synced form definition (form_id) and written on the service. For a scored questionnaire, per-question scores are entered and totals and risk bands are derived by the EMR. - Read-back — after signing, the service is re-read from the EMR to confirm it persisted before the success webhook is sent.
Request Parameters
Required Fields
- patient_mrn (string, required): The patient’s medical record number. For Credible this is the client id. The patient must already be synced to Cobalt.
- team (string, required): Team name (or numeric team id) that owns the episode. Assigning the client to the team opens the episode when one does not already exist. The name is matched case-insensitively, preferring an exact match over a partial one.
- service_type (string, required): The service type to add, by name or numeric visit-type id (for example
"GAD-7"). Must be billable for the client — that is, present in the client’s billing matrix. - form_id (string, required): EMR form id whose answers you are providing — the
emr_form_idof a form fromGET /v1/forms. Required when the service type documents a form. - answers (object, required): Form answers keyed by EMR question id (the
emrQuestionIdof each question in the form definition — seeGET /v1/forms/{id}). For a scored questionnaire, provide the numeric score for each scored question; totals and risk bands are derived automatically. Answers are validated against the synced form definition before the service is written.
Optional Fields
- service_date (string, optional): Service date in
YYYY-MM-DDformat. Defaults to today. Cannot be in the future. - callback_urls (array of strings, optional): URLs to receive the completion webhook for this service, in addition to your account webhook.
Example Request
curl -X POST https://api.usecobalt.com/v1/services \
-H 'Content-Type: application/json' \
-H 'client_id: ci_live_198908HJDKJSH98789OHKJL' \
-H 'client_secret: cs_live_9827hofdsklOYYHJLJh' \
-H 'access_token: 493JKLHIU98789hLKH9HHJH' \
-d '{
"patient_mrn": "1234567",
"team": "Adult Outpatient",
"service_type": "GAD-7",
"form_id": "392",
"service_date": "2026-08-26",
"answers": {
"453149": "3",
"453150": "2",
"453156": "Very difficult"
}
}'
Example Response
{
"success": true,
"message": "Service processing. A webhook event will be sent upon completion.",
"service_id": "123e4567e89b12d3a456426614174000",
"job_id": 12345
}
- service_id: Cobalt service ID (UUID without dashes). This is echoed back in the webhook payload so you can correlate the two.
- job_id: Job execution identifier for tracking the async operation.
Error Responses
Missing Required Field
{
"success": false,
"message": "Missing required field: patient_mrn"
}
Answers Not An Object
{
"success": false,
"message": "answers must be an object keyed by EMR question id."
}
Invalid Service Date
{
"success": false,
"message": "service_date must be a valid date (YYYY-MM-DD)."
}
{
"success": false,
"message": "service_date cannot be in the future."
}
User Not Found
{
"success": false,
"message": "User not found."
}
Unsupported EMR
{
"success": false,
"message": "Creating services is not supported for [EMR Name]."
}
Webhook Notifications
When the service has finished processing, we send a webhook to your registered endpoint.Success
{
"id": "<id-of-webhook-response>",
"access_token_reference_id": "<access-token-reference-id>",
"object": "event",
"created": "2026-08-26T10:30:00.000Z",
"type": "service.created",
"data": {
"service_id": "123e4567e89b12d3a456426614174000",
"emr_service_id": "927341",
"emr_episode_id": "88214",
"patient_mrn": "1234567"
}
}
- service_id: The Cobalt service ID you received in the response.
- emr_service_id: The service’s id in the EMR.
- emr_episode_id: The episode the service was written under (reused if one was already open, otherwise the episode opened by the team assignment).
- patient_mrn: The patient’s medical record number.
Failure
{
"id": "<id-of-webhook-response>",
"access_token_reference_id": "<access-token-reference-id>",
"object": "event",
"created": "2026-08-26T10:35:00.000Z",
"type": "service.failed",
"data": {
"service_id": "123e4567e89b12d3a456426614174000",
"emr_service_id": null,
"patient_mrn": "1234567",
"failure_reason": "Service type 'GAD-7' not available for client 1234567 (not in billing matrix)"
}
}
service.failed event is sent once, when the failure is permanent. Common failure_reason values:
Credible team '<team>' not found for client <mrn>— the team name or id did not match a team the client can be assigned to.Service type '<type>' not available for client <mrn> (not in billing matrix)— the service type is not billable for the client.Missing required answers: <question ids>— one or more required form questions were not answered.
Authorizations
Body
Medical Record Number (Credible client id) of the patient.
"15539"
Team name (or numeric team id) that owns the episode. Assigning the client to the team creates the episode when one does not already exist.
"TestClinic"
Service type to add, by name or numeric visit-type id (e.g. "GAD-7").
"GAD-7"
EMR form id whose answers are provided (from GET /v1/forms). Required when the service type documents a form.
"392"
Form answers keyed by EMR question id. For a scored questionnaire (e.g. GAD-7) provide the numeric score for each scored question; totals and risk bands are derived automatically.
Show child attributes
Show child attributes
{
"453149": "3",
"453150": "2",
"453156": "Very difficult"
}
Service date (YYYY-MM-DD). Defaults to today. Cannot be in the future.
"2026-08-26"
URLs to receive the completion webhook for this service, in addition to the account webhook.