Question

How do I make a simple PHP API handler for Digital Ocean?

Hi all,

I’ve having some trouble understanding the API, in the past with other API’s I’ve just used a simple PHP with curl script to action a specific task on a service. I don’t need a full library and the Digital Ocean has more dependencies than I care to count…

For some reason the DO API is not working with a simple script like this while others do, I must be missing something?

function basic_api_handle($key, $method, $URI, $data) {

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Authorization: Bearer '.$key,
        'Content-Type: application/json')
    );

    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
    curl_setopt($ch, CURLOPT_URL, $URI);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));

    $result = curl_exec($ch);
    if($result === false) error_log("API ERROR: Connection failure: $URI", 0);

    curl_close($ch);

    return json_decode($result, true);
}

var_dump(basic_api_handle($api_key, 'POST', 'https://api.digitalocean.com/v2/domains', array('name' => 'my-domain.tld', 'ip_address' => '1.2.3.4')));

This results in** “unprocessable_entity” **and “Name can’t be blank” - it suggests to me the data is not being sent correctly? although, as far as I can tell, it is…

I’ve also posted this on Stack Overflow but it may be to specific (Digital Ocean) to get any decent answers. I have setup a bounty for a solution too :) http://stackoverflow.com/questions/43619504/how-do-i-make-a-simple-php-api-handler/43854037


Submit an answer


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Accepted Answer

@hozza

A very simple way to do this, without curl would be using file_get_contents and streams.

<?php
function doapi( $key, $method, $uri, array $data = [] )
{
    /**
     * DigitalOcean API URI
     */
    $api = 'https://api.digitalocean.com/v2';

    /**
     * Merge DigitalOcean API URI and Endpoint URI
     *
     * i.e if $uri is set to 'domains', then $api ends up as
     *     $api = 'https://api.digitalocean.com/v2/domains'
     */
    $uri = $api . DIRECTORY_SEPARATOR . $uri;

    /**
     * Define Authorization and Content-Type Header.
     */
    $headers = "Authorization: Bearer $key \r\n" .
               "Content-Type: application/json";

    /**
     * If $data array is not empty, assume we're passing data, so we'll encode
     * it and pass it to 'content'. If $data is empty, assume we're not passing
     * data, so we won't sent 'content'.
     */
    if ( ! empty( $data ) )
    {
        $data = [
                    'http'          => [
                        'method'    =>  strtoupper( $method ),
                        'header'    =>  $headers,
                        'content'   =>  json_encode( $data )
                    ]
                ];
    }
    else
    {
        $data = [
                    'http'          => [
                        'method'    =>  strtoupper( $method ),
                        'header'    =>  $headers
                    ]
                ];
    }

    /**
     * Create Stream Context
     * http://php.net/manual/en/function.stream-context-create.php
     */
    $context = stream_context_create( $data );

    /**
     * Send Request and Store to $response.
     */
    $response = file_get_contents( $uri, false, $context );

    /**
     * Return as decoded JSON (i.e. an array)
     */
    return json_decode( $response, true );
}

/**
 * Example Usage
 */

var_dump(doapi(
    'do-api-key',
    'get',
    'domains'
));

An example is at the bottom of the file.

var_dump(doapi(
    'do-api-key',
    'get',
    'domains'
));

Which just dumps the output of the response. You could assign it to a variable, like so:

$response = doapi( 'do-api-key', 'get', 'domains' );

You could then filter through the response as needed. The above is very basic and doesn’t have any sort of error handling built-in, so you’d need to make sure you’re passing exactly what is required.

Looking at the initial function definition:

function doapi( $key, $method, $uri, array $data = [] )

You’ll pass:

$key = DigitalOcean API Key

$method = Upper or Lowercase Method (get, post, delete, etc). It’ll be converted to uppercase.

$uri = The endpoint your calling, without a / (i.e. domains, droplets, etc).

$data = An array of data that isn’t JSON encoded (the function will encode it for you).

For $uri, you could pass endpoints with a slash between them, i.e. domains/action (where action is an endpoint off domains`), though no front or trailing slash should be added.

I just tested this locally using one of my API keys and it works. Hopefully that’ll help :-).

@hozza

No problem at all, happy to help :-). I’ve not been on SO in a while – I probably need to get back on there at some point.

As a side note, if you want to tinker with cURL too, here’s a modified version of the original function from my first post. It only handles GET and POST requests as-is, but you can extend the function to handle PUT, DELETE, etc as needed.

<?php
function doapi( $key, $method, $uri, array $data = [] )
{
    $api        =   'https://api.digitalocean.com/v2';
    $uri        =   $api . DIRECTORY_SEPARATOR . $uri;
    $method     =   strtoupper( $method );

    $headers    =   [
                        "Authorization: Bearer $key",
                        "Content-Type: application/json"
                    ];

    $ch         =   curl_init();

    curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
    curl_setopt( $ch, CURLOPT_URL, $uri );

    if ( $method === 'POST' && ! empty( $data ) )
    {
        curl_setopt( $ch, CURLOPT_POST, 1 );
        curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $data ) );
    }

    $result     =   curl_exec( $ch );
    $result     =   json_decode( $result, true );

    curl_close( $ch );

    return $result;
}

$result = doapi(
    'do-api-key',
    'post',
    'droplets',
    [
        'name' => 'example.com',
        'region' => 'nyc3',
        'size' => '512mb',
        'image' => 'ubuntu-16-04-x64'
    ]
);

var_dump( $result );

The only difference is the code. You’d use it the same as you do the other function. Hopefully that’ll help you either way – using whichever method you prefer to use :-).

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel