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 :-).

Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in Q&A, subscribe to topics of interest, and get courses and tools that will help you grow as a developer and scale your project or business.

@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 :-).