Skip to content
← Back to Snippets
Code

Basic cURL POST Request with JSON

Posts a JSON payload with cURL, validates HTTPS, sets JSON headers, and returns decoded response data when possible.

Purpose

Posts a JSON payload with cURL, validates HTTPS, sets JSON headers, and returns decoded response data when possible.

Snippet details

ContextHttpLevelProductionCopy-and-paste statusMarked safe after review.

Categories

  • Forms and Validation

Code

<?php

/*
 * Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
 * Free for personal and internal use. Paid project use requires visible credit
 * to Jeffery L. Paris. Corporate use requires a paid license fee unless a
 * separate written license states otherwise.
 */

/**
 * Basic cURL POST Request with JSON.
 *
 * Purpose:
 * Sends a JSON POST request to an HTTPS endpoint with cURL and returns a
 * structured result that separates transport failure from HTTP failure.
 *
 * @param string $endpoint_url HTTPS endpoint URL.
 * @param array $payload Payload to JSON encode.
 * @return array Request status, HTTP code, decoded response, raw body, and message.
 */
function ogSnippetCurlPostRequestJson(string $endpoint_url, array $payload): array {
	$endpoint_url = trim($endpoint_url);

	if (filter_var($endpoint_url, FILTER_VALIDATE_URL) === false) {
		return array('success' => false, 'http_code' => 0, 'decoded' => null, 'body' => '', 'message' => 'Endpoint URL is invalid.');
	}

	$parts = parse_url($endpoint_url);
	if (isset($parts['scheme']) === false || strtolower((string) $parts['scheme']) !== 'https') {
		return array('success' => false, 'http_code' => 0, 'decoded' => null, 'body' => '', 'message' => 'Only HTTPS endpoints are allowed.');
	}

	$json_payload = json_encode($payload, JSON_UNESCAPED_SLASHES);
	if ($json_payload === false) {
		return array('success' => false, 'http_code' => 0, 'decoded' => null, 'body' => '', 'message' => 'Payload could not be encoded as JSON.');
	}

	$curl_handle = curl_init($endpoint_url);
	if ($curl_handle === false) {
		return array('success' => false, 'http_code' => 0, 'decoded' => null, 'body' => '', 'message' => 'cURL could not initialize.');
	}

	$headers = array(
		'Content-Type: application/json; charset=UTF-8',
		'Accept: application/json'
	);

	curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($curl_handle, CURLOPT_POST, true);
	curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $json_payload);
	curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $headers);
	curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 5);
	curl_setopt($curl_handle, CURLOPT_TIMEOUT, 15);

	$response_body = curl_exec($curl_handle);
	$curl_error = curl_error($curl_handle);
	$http_code = (int) curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);
	curl_close($curl_handle);

	if ($response_body === false) {
		return array('success' => false, 'http_code' => $http_code, 'decoded' => null, 'body' => '', 'message' => 'JSON POST failed: '.$curl_error);
	}

	$decoded_response = json_decode((string) $response_body, true);
	if (is_array($decoded_response) === false) {
		$decoded_response = null;
	}

	if ($http_code < 200 || $http_code >= 300) {
		return array('success' => false, 'http_code' => $http_code, 'decoded' => $decoded_response, 'body' => (string) $response_body, 'message' => 'JSON POST returned HTTP '.$http_code.'.');
	}

	return array('success' => true, 'http_code' => $http_code, 'decoded' => $decoded_response, 'body' => (string) $response_body, 'message' => 'JSON POST completed.');
}

/*
$payload = array(
	'ship' => 'Serenity',
	'job' => 'supply drop',
	'status' => 'green'
);
$result = ogSnippetCurlPostRequestJson('https://example.com/firefly/jobs', $payload);
print_r($result);
*/