Quick start

In Laravel, use the facade or resolve Darvis\BullhornApi\Client from the container. Never construct the client yourself in a Laravel application: the container’s client has the shared session cache.

use Darvis\BullhornApi\Laravel\Facades\Bullhorn;

Every method returns Bullhorn’s decoded answer as an array, unchanged. Most answers have the result in data.

Is Bullhorn alive?

Start here: it tells you whether your credentials and the connection work.

if (! Bullhorn::isAlive()) {
    // Show "we are working on it". ping() in a try/catch tells you why.
}

isAlive() never throws. Without a session it logs in, so keep the answer for a minute with Cache::remember() instead of asking on every page view. More in Examples.

Read an entity

Bullhorn wants to know which fields to return.

$candidate = Bullhorn::entity('Candidate', 123, ['id', 'firstName', 'lastName', 'email'])['data'];

$several = Bullhorn::entity('Candidate', [123, 124], 'id,firstName')['data'];

Create and update

Bullhorn creates with PUT and updates with POST. The helpers pick the right verb:

$id = Bullhorn::createEntity('Candidate', [
    'firstName' => 'Anna',
    'lastName' => 'Smit',
    'name' => 'Anna Smit',
])['changedEntityId'];

Bullhorn::updateEntity('Candidate', $id, ['phone' => '0612345678']);

Bullhorn::deleteEntity('CandidateEducation', 77);

Search and query

search() is for the entities Bullhorn indexes, such as Candidate, JobOrder and JobSubmission, with a Lucene query. query() is for the others, with a where clause.

$found = Bullhorn::search('Candidate', 'email:"anna@example.com"', ['id', 'firstName'], ['count' => 1]);

$submissions = Bullhorn::search('JobSubmission', 'candidate.id:'.$id, 'id,jobOrder,status');

$categories = Bullhorn::query('Category', 'enabled=true', 'id,name', ['count' => 500]);

Upload a file

upload() sends one file as multipart form data. To let Bullhorn parse a CV:

$parsed = Bullhorn::upload('POST', 'resume/parseToCandidate', 'cv.pdf', file_get_contents($path), 'application/pdf', [
    'format' => 'text',
]);

Any other endpoint

Paths are relative to the REST URL of your corporation. A path may carry its own query string.

Bullhorn::get('settings/userId');
Bullhorn::post('entity/Candidate/'.$id, ['customText1' => 'yes']);
Bullhorn::put('entity/Note', ['comments' => 'Called', 'personReference' => ['id' => $id]]);

When it fails

use Darvis\BullhornApi\Exceptions\AuthenticationException;
use Darvis\BullhornApi\Exceptions\BullhornException;

try {
    Bullhorn::updateEntity('Candidate', $id, $data);
} catch (AuthenticationException $e) {
    // The login failed: the credentials need fixing. Tell the visitor the service is down.
    report($e);
} catch (BullhornException $e) {
    $e->status();        // 400
    $e->errorKey();      // 'errors.cannotPersistEntity'
    $e->invalidFields(); // ['customText1']
}

Bullhorn refuses the whole entity when one field is wrong: one value that is too long and nothing is saved. Validate lengths and types before you send. The message of the exception holds the whole response, so the field Bullhorn names is never cut off.