Testing the HelloCRM public API
All samples call the API at https://api.hellocrm.ai (that is your baseUrl in Postman). This
page may be served from https://developers.hellocrm.ai or locally—only the API host matters for these
requests. Replace with your environment if needed. Authenticate with header
x-api-key: YOUR_TEAM_API_KEY (or Authorization: Bearer … where your backend allows JWT).
Use Idempotency-Key on creates and sends when you may retry.
cURL
Create contact (minimal example).
curl -sS -X POST "https://api.hellocrm.ai/api/contacts" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "x-api-key: YOUR_TEAM_API_KEY" \
-H "Idempotency-Key: $(uuidgen 2>/dev/null || echo idem-$(date +%s))" \
-d '{
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada@example.com",
"phone": "+15555550100",
"status": "open",
"source": "API",
"lifecycleStage": "Lead",
"groupIds": [],
"additionalFields": {}
}'
JavaScript (fetch, Node 18+ or browsers)
const baseUrl = "https://api.hellocrm.ai";
const apiKey = process.env.HELLOCRM_API_KEY; // or hard-code for local tests only
const res = await fetch(`${baseUrl}/api/contacts`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"x-api-key": apiKey,
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
firstName: "Ada",
lastName: "Lovelace",
email: "ada@example.com",
phone: "+15555550100",
status: "open",
source: "API",
lifecycleStage: "Lead",
groupIds: [],
additionalFields: {},
}),
});
console.log(res.status, await res.text());
TypeScript (fetch)
const baseUrl = "https://api.hellocrm.ai";
async function createContact(apiKey: string): Promise<unknown> {
const res = await fetch(`${baseUrl}/api/contacts`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"x-api-key": apiKey,
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
firstName: "Ada",
lastName: "Lovelace",
email: "ada@example.com",
phone: "+15555550100",
status: "open",
source: "API",
lifecycleStage: "Lead",
groupIds: [],
additionalFields: {},
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
return res.json();
}
Python 3 (urllib, standard library)
import json
import ssl
import urllib.request
import uuid
BASE = "https://api.hellocrm.ai"
API_KEY = "YOUR_TEAM_API_KEY"
body = {
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada@example.com",
"phone": "+15555550100",
"status": "open",
"source": "API",
"lifecycleStage": "Lead",
"groupIds": [],
"additionalFields": {},
}
req = urllib.request.Request(
f"{BASE}/api/contacts",
data=json.dumps(body).encode("utf-8"),
method="POST",
headers={
"Content-Type": "application/json",
"Accept": "application/json",
"x-api-key": API_KEY,
"Idempotency-Key": str(uuid.uuid4()),
},
)
ctx = ssl.create_default_context()
with urllib.request.urlopen(req, context=ctx) as resp:
print(resp.status, resp.read().decode("utf-8"))
With requests: pip install requests then use requests.post(url, headers=…, json=body).
Go (net/http)
package main
import (
"bytes"
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
apiKey := os.Getenv("HELLOCRM_API_KEY")
body := map[string]any{
"firstName": "Ada", "lastName": "Lovelace", "email": "ada@example.com",
"phone": "+15555550100", "status": "open", "source": "API",
"lifecycleStage": "Lead", "groupIds": []string{}, "additionalFields": map[string]any{},
}
b, _ := json.Marshal(body)
req, _ := http.NewRequest(http.MethodPost, "https://api.hellocrm.ai/api/contacts", bytes.NewReader(b))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
req.Header.Set("x-api-key", apiKey)
var idem [16]byte
_, _ = rand.Read(idem[:])
req.Header.Set("Idempotency-Key", hex.EncodeToString(idem[:]))
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
fmt.Println(res.Status)
}
Java 17+ (java.net.http.HttpClient)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;
public class HelloCrmSmoke {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("HELLOCRM_API_KEY");
String json = """
{"firstName":"Ada","lastName":"Lovelace","email":"ada@example.com","phone":"+15555550100",
"status":"open","source":"API","lifecycleStage":"Lead","groupIds":[],"additionalFields":{}}
""";
var req = HttpRequest.newBuilder(URI.create("https://api.hellocrm.ai/api/contacts"))
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.header("x-api-key", apiKey)
.header("Idempotency-Key", UUID.randomUUID().toString())
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
var client = HttpClient.newHttpClient();
var res = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.statusCode() + " " + res.body());
}
}
C# / .NET (HttpClient)
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
var apiKey = Environment.GetEnvironmentVariable("HELLOCRM_API_KEY")
?? throw new InvalidOperationException("HELLOCRM_API_KEY");
var payload = new
{
firstName = "Ada",
lastName = "Lovelace",
email = "ada@example.com",
phone = "+15555550100",
status = "open",
source = "API",
lifecycleStage = "Lead",
groupIds = Array.Empty<string>(),
additionalFields = new { },
};
using var client = new HttpClient { BaseAddress = new Uri("https://api.hellocrm.ai/") };
using var req = new HttpRequestMessage(HttpMethod.Post, "api/contacts");
req.Headers.TryAddWithoutValidation("x-api-key", apiKey);
req.Headers.TryAddWithoutValidation("Idempotency-Key", Guid.NewGuid().ToString());
req.Content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var res = await client.SendAsync(req);
Console.WriteLine((int)res.StatusCode + " " + await res.Content.ReadAsStringAsync());
Ruby (net/http)
require "json"
require "net/http"
require "uri"
require "securerandom"
uri = URI("https://api.hellocrm.ai/api/contacts")
body = {
"firstName" => "Ada",
"lastName" => "Lovelace",
"email" => "ada@example.com",
"phone" => "+15555550100",
"status" => "open",
"source" => "API",
"lifecycleStage" => "Lead",
"groupIds" => [],
"additionalFields" => {}
}
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Content-Type"] = "application/json"
req["Accept"] = "application/json"
req["x-api-key"] = ENV.fetch("HELLOCRM_API_KEY")
req["Idempotency-Key"] = SecureRandom.uuid
req.body = JSON.generate(body)
res = http.request(req)
puts "#{res.code} #{res.body}"
PHP 8+ (file_get_contents stream context)
<?php
$base = "https://api.hellocrm.ai";
$apiKey = getenv("HELLOCRM_API_KEY") ?: "YOUR_TEAM_API_KEY";
$body = json_encode([
"firstName" => "Ada",
"lastName" => "Lovelace",
"email" => "ada@example.com",
"phone" => "+15555550100",
"status" => "open",
"source" => "API",
"lifecycleStage" => "Lead",
"groupIds" => [],
"additionalFields" => new stdClass(),
]);
$ctx = stream_context_create([
"http" => [
"method" => "POST",
"header" =>
"Content-Type: application/json\r\n" .
"Accept: application/json\r\n" .
"x-api-key: {$apiKey}\r\n" .
"Idempotency-Key: " . bin2hex(random_bytes(16)) . "\r\n",
"content" => $body,
"ignore_errors" => true,
],
]);
$res = file_get_contents("{$base}/api/contacts", false, $ctx);
var_dump($http_response_header ?? null, $res);
Opening tag shown escaped for HTML; in your .php file start with <?php as usual.
Postman CLI (Newman) in CI
Run the collection headlessly after importing environment secrets in your pipeline.
npm install -g newman newman run hello-crm.postman_collection.json \ --env-var "baseUrl=https://api.hellocrm.ai" \ --env-var "apiKey=$HELLOCRM_API_KEY"
Download the collection from this site (JSON) or use the copy under
postman/HelloCRM.postman_collection.json in the repo. Add tests in Postman and export the collection to keep
Newman in sync.