Overview
GoBlue uses API key-based authentication to secure access to your account data and messaging capabilities. This guide covers how to obtain, manage, and use API keys securely.
Authentication Methods
GoBlue supports two authentication approaches depending on the endpoint:
Form-Based (Webhooks) Uses form ID in URL for webhook endpoints - no API key required
API Key (Direct Access) Uses API key for direct API access to messages, forms, and account data
API Key Management
Obtaining Your API Key
Open GoBlue App
Launch the GoBlue app on your iOS device.
Navigate to Settings
Tap the “Settings” tab at the bottom of the screen.
Find API Access Section
Scroll to the “API Access” section where your API key is displayed.
Copy API Key
Tap the copy button to copy your API key to the clipboard. Your API key is sensitive information. Never share it publicly or commit it to version control.
GoBlue API keys follow this format:
goblue_sk_1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t
Structure:
Prefix : goblue_sk_ (indicates GoBlue secret key)
Key : 40-character alphanumeric string
Total Length : 50 characters
Authentication Implementation
URL Path Authentication
For message retrieval and some endpoints, include the API key in the URL path:
GET https://api.goblue.app/v1/messages/{api-key}
Example:
curl https://api.goblue.app/v1/messages/goblue_sk_1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t
For other endpoints, use the Authorization header:
Authorization : Bearer {api-key}
Example:
curl -H "Authorization: Bearer goblue_sk_1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t" \
https://api.goblue.app/v1/forms
Webhook Authentication
Webhook endpoints use form-based authentication:
POST https://api.goblue.app/v1/forms/{form-id}/webhook
The form-id serves as both the endpoint identifier and authentication token.
Programming Language Examples
JavaScript/Node.js
const GOBLUE_API_KEY = process . env . GOBLUE_API_KEY ;
// URL path method
async function getMessages () {
const response = await fetch ( `https://api.goblue.app/v1/messages/ ${ GOBLUE_API_KEY } ` );
return response . json ();
}
// Header method
async function getForms () {
const response = await fetch ( 'https://api.goblue.app/v1/forms' , {
headers: {
'Authorization' : `Bearer ${ GOBLUE_API_KEY } ` ,
'Content-Type' : 'application/json'
}
});
return response . json ();
}
// Webhook (no API key needed)
async function sendWebhook ( formId , data ) {
const response = await fetch ( `https://api.goblue.app/v1/forms/ ${ formId } /webhook` , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json'
},
body: JSON . stringify ( data )
});
return response . json ();
}
Python
import os
import requests
API_KEY = os.getenv( 'GOBLUE_API_KEY' )
BASE_URL = 'https://api.goblue.app/v1'
# URL path method
def get_messages ():
url = f " { BASE_URL } /messages/ { API_KEY } "
response = requests.get(url)
return response.json()
# Header method
def get_forms ():
url = f " { BASE_URL } /forms"
headers = {
'Authorization' : f 'Bearer { API_KEY } ' ,
'Content-Type' : 'application/json'
}
response = requests.get(url, headers = headers)
return response.json()
# Webhook (no API key needed)
def send_webhook ( form_id , data ):
url = f " { BASE_URL } /forms/ { form_id } /webhook"
headers = { 'Content-Type' : 'application/json' }
response = requests.post(url, json = data, headers = headers)
return response.json()
PHP
<? php
class GoBlueAPI {
private $apiKey ;
private $baseUrl = 'https://api.goblue.app/v1' ;
public function __construct ( $apiKey ) {
$this -> apiKey = $apiKey ;
}
// URL path method
public function getMessages () {
$url = "{ $this -> baseUrl }/messages/{ $this -> apiKey }" ;
return $this -> makeRequest ( $url , 'GET' );
}
// Header method
public function getForms () {
$url = "{ $this -> baseUrl }/forms" ;
$headers = [
"Authorization: Bearer { $this -> apiKey }" ,
"Content-Type: application/json"
];
return $this -> makeRequest ( $url , 'GET' , null , $headers );
}
// Webhook (no API key needed)
public function sendWebhook ( $formId , $data ) {
$url = "{ $this -> baseUrl }/forms/{ $formId }/webhook" ;
$headers = [ "Content-Type: application/json" ];
return $this -> makeRequest ( $url , 'POST' , $data , $headers );
}
private function makeRequest ( $url , $method , $data = null , $headers = []) {
$ch = curl_init ();
curl_setopt_array ( $ch , [
CURLOPT_URL => $url ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_CUSTOMREQUEST => $method ,
CURLOPT_HTTPHEADER => $headers
]);
if ( $data ) {
curl_setopt ( $ch , CURLOPT_POSTFIELDS , json_encode ( $data ));
}
$response = curl_exec ( $ch );
$httpCode = curl_getinfo ( $ch , CURLINFO_HTTP_CODE );
curl_close ( $ch );
if ( $httpCode !== 200 ) {
throw new Exception ( "API request failed: HTTP { $httpCode }" );
}
return json_decode ( $response , true );
}
}
// Usage
$api = new GoBlueAPI ( $_ENV [ 'GOBLUE_API_KEY' ]);
$messages = $api -> getMessages ();
?>
Ruby
require 'net/http'
require 'json'
require 'uri'
class GoBlueAPI
BASE_URL = 'https://api.goblue.app/v1'
def initialize ( api_key )
@api_key = api_key
end
# URL path method
def get_messages
uri = URI ( " #{ BASE_URL } /messages/ #{ @api_key } " )
make_request (uri, Net :: HTTP :: Get )
end
# Header method
def get_forms
uri = URI ( " #{ BASE_URL } /forms" )
request = Net :: HTTP :: Get . new (uri)
request[ 'Authorization' ] = "Bearer #{ @api_key } "
request[ 'Content-Type' ] = 'application/json'
make_request (uri, request)
end
# Webhook (no API key needed)
def send_webhook ( form_id , data )
uri = URI ( " #{ BASE_URL } /forms/ #{ form_id } /webhook" )
request = Net :: HTTP :: Post . new (uri)
request[ 'Content-Type' ] = 'application/json'
request. body = data. to_json
make_request (uri, request)
end
private
def make_request ( uri , request )
http = Net :: HTTP . new (uri. host , uri. port )
http. use_ssl = true
response = http. request (request)
unless response. code == '200'
raise "API request failed: HTTP #{ response. code } "
end
JSON . parse (response. body )
end
end
# Usage
api = GoBlueAPI . new ( ENV [ 'GOBLUE_API_KEY' ])
messages = api. get_messages
Security Best Practices
API Key Protection
Store API keys in environment variables, never in code: # .env file
GOBLUE_API_KEY = goblue_sk_1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t
// Access in code
const apiKey = process . env . GOBLUE_API_KEY ;
Never commit API keys to version control: # .gitignore
.env
*.key
config/secrets.json
Use placeholder values in example files: // config.example.js
module . exports = {
goblueApiKey: 'your-api-key-here'
};
Additional security measures for production:
Use secret management services (AWS Secrets Manager, Azure Key Vault)
Rotate API keys periodically
Monitor API key usage for suspicious activity
Implement IP whitelisting if possible
HTTPS Only
Always use HTTPS when making API requests. HTTP requests may expose your API key during transmission.
// ✅ Correct - HTTPS
const response = await fetch ( 'https://api.goblue.app/v1/messages/...' );
// ❌ Never use HTTP
const response = await fetch ( 'http://api.goblue.app/v1/messages/...' );
Request Logging
When logging API requests, never log the full API key:
// ✅ Safe logging
console . log ( 'API request' , {
url: url . replace ( apiKey , 'sk_***' ),
method: 'GET' ,
timestamp: new Date (). toISOString ()
});
// ❌ Dangerous - exposes API key
console . log ( 'API request' , { url , apiKey , method: 'GET' });
Error Handling
Authentication Errors
Cause : Invalid or missing API keyResponse: {
"status" : "error" ,
"message" : "Invalid API key" ,
"code" : "AUTHENTICATION_ERROR" ,
"details" : {
"provided" : "goblue_sk_invalid..." ,
"expected" : "Valid GoBlue API key"
}
}
Solutions:
Verify API key is correct
Check for extra spaces or characters
Ensure key hasn’t been regenerated
Cause : API key lacks required permissionsResponse: {
"status" : "error" ,
"message" : "Insufficient permissions for this endpoint" ,
"code" : "PERMISSION_ERROR" ,
"details" : {
"endpoint" : "/v1/admin/users" ,
"required" : "admin_access" ,
"current" : "standard_access"
}
}
Solutions:
Contact support for permission upgrade
Use appropriate endpoint for your access level
Implementing Error Handling
class GoBlueAuthError extends Error {
constructor ( message , code , details ) {
super ( message );
this . name = 'GoBlueAuthError' ;
this . code = code ;
this . details = details ;
}
}
async function authenticatedRequest ( url , options = {}) {
try {
const response = await fetch ( url , {
... options ,
headers: {
'Authorization' : `Bearer ${ process . env . GOBLUE_API_KEY } ` ,
'Content-Type' : 'application/json' ,
... options . headers
}
});
if ( ! response . ok ) {
const errorData = await response . json ();
if ( response . status === 401 || response . status === 403 ) {
throw new GoBlueAuthError (
errorData . message ,
errorData . code ,
errorData . details
);
}
throw new Error ( `HTTP ${ response . status } : ${ errorData . message } ` );
}
return response . json ();
} catch ( error ) {
if ( error instanceof GoBlueAuthError ) {
console . error ( 'Authentication failed:' , error . message );
// Handle specific auth errors
switch ( error . code ) {
case 'AUTHENTICATION_ERROR' :
// Invalid API key - check configuration
throw new Error ( 'Please check your GoBlue API key configuration' );
case 'PERMISSION_ERROR' :
// Insufficient permissions - use different endpoint
throw new Error ( 'This operation requires additional permissions' );
default :
throw error ;
}
}
throw error ; // Re-throw other errors
}
}
API Key Rotation
When to Rotate
Scheduled Rotation Rotate keys every 90 days as a security best practice
Security Incident Immediately rotate if key may have been compromised
Team Changes Rotate when team members with key access leave
System Changes Rotate during major system upgrades or migrations
Rotation Process
Generate New Key
Contact GoBlue support to generate a new API key while keeping the old one active.
Update Applications
Update all applications and integrations to use the new API key.
Test Thoroughly
Verify all integrations work with the new key before deactivating the old one.
Deactivate Old Key
Once confirmed working, have the old API key deactivated.
Monitor
Monitor for any failed requests that might indicate missed integrations.
Rate Limiting with Authentication
API keys are subject to rate limiting:
Standard Limits 1,000 requests per hour per API key
Burst Allowance Up to 100 requests per minute for short bursts
Authentication requests include rate limit information:
HTTP / 1.1 200 OK
X-RateLimit-Limit : 1000
X-RateLimit-Remaining : 987
X-RateLimit-Reset : 1640995200
X-RateLimit-Burst-Limit : 100
X-RateLimit-Burst-Remaining : 95
Handling Rate Limits
async function rateLimitAwareRequest ( url , options ) {
const response = await fetch ( url , options );
// Check rate limit headers
const remaining = parseInt ( response . headers . get ( 'X-RateLimit-Remaining' ));
const reset = parseInt ( response . headers . get ( 'X-RateLimit-Reset' ));
if ( remaining < 10 ) {
const resetTime = new Date ( reset * 1000 );
console . warn ( `Rate limit nearly exceeded. Resets at: ${ resetTime } ` );
}
if ( response . status === 429 ) {
const retryAfter = response . headers . get ( 'Retry-After' ) || 60 ;
throw new Error ( `Rate limited. Retry after ${ retryAfter } seconds` );
}
return response ;
}
Testing Authentication
Development Testing
# Test API key validity
curl -I https://api.goblue.app/v1/messages/YOUR_API_KEY
# Expected response for valid key
HTTP/2 200
content-type: application/json
x-ratelimit-limit: 1000
x-ratelimit-remaining: 999
# Expected response for invalid key
HTTP/2 401
content-type: application/json
Automated Testing
describe ( 'GoBlue API Authentication' , () => {
const validApiKey = process . env . GOBLUE_API_KEY ;
const invalidApiKey = 'goblue_sk_invalid' ;
test ( 'should authenticate with valid API key' , async () => {
const response = await fetch ( `https://api.goblue.app/v1/messages/ ${ validApiKey } ` );
expect ( response . status ). toBe ( 200 );
});
test ( 'should reject invalid API key' , async () => {
const response = await fetch ( `https://api.goblue.app/v1/messages/ ${ invalidApiKey } ` );
expect ( response . status ). toBe ( 401 );
const data = await response . json ();
expect ( data . code ). toBe ( 'AUTHENTICATION_ERROR' );
});
test ( 'should include rate limit headers' , async () => {
const response = await fetch ( `https://api.goblue.app/v1/messages/ ${ validApiKey } ` );
expect ( response . headers . get ( 'X-RateLimit-Limit' )). toBeTruthy ();
expect ( response . headers . get ( 'X-RateLimit-Remaining' )). toBeTruthy ();
});
});
Support and Troubleshooting
Common Issues
Symptoms : 401 errors despite having an API keyTroubleshooting :
Verify the key is copied correctly (check for extra spaces)
Ensure you’re using the latest key from the app
Test with a simple curl request
Check if the key was recently regenerated
Intermittent Authentication Failures
Symptoms : Authentication works sometimes but fails other timesTroubleshooting :
Check for rate limiting (429 responses)
Verify all application instances use the same key
Look for network connectivity issues
Monitor for API key rotation events
Symptoms : 403 errors for certain endpointsTroubleshooting :
Verify you’re using the correct endpoint
Check if your account has the required permissions
Contact support for permission questions
Review API documentation for endpoint requirements
Getting Help
Next Steps