PHPackages                             vincentauger/datacite-php-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. vincentauger/datacite-php-sdk

ActiveLibrary[API Development](/categories/api)

vincentauger/datacite-php-sdk
=============================

A modern PHP SDK for DataCite API

v1.3.1(1mo ago)115MITPHPPHP ^8.4.0CI passing

Since Nov 5Pushed 1mo agoCompare

[ Source](https://github.com/vincentauger/datacite-php-sdk)[ Packagist](https://packagist.org/packages/vincentauger/datacite-php-sdk)[ Docs](https://github.com/vincentauger/datacite-php-sdk)[ RSS](/packages/vincentauger-datacite-php-sdk/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (6)Dependencies (14)Versions (9)Used By (0)

DataCite PHP SDK (Unofficial)
=============================

[](#datacite-php-sdk-unofficial)

A modern PHP SDK for the [DataCite REST API](https://support.datacite.org/docs/api), built for maintainability and clarity using [Saloon](https://docs.saloon.dev) for HTTP integration.

[![Tests](https://github.com/vincentauger/datacite-php-sdk/actions/workflows/tests.yml/badge.svg)](https://github.com/vincentauger/datacite-php-sdk/actions/workflows/tests.yml)[![DOI](https://camo.githubusercontent.com/60e25cb3758366f0d1df32d5fe328919ebc1e65ed521935119fb5a95842da0f3/68747470733a2f2f7a656e6f646f2e6f72672f62616467652f313032323232303836322e737667)](https://doi.org/10.5281/zenodo.17536592)

Features
--------

[](#features)

- ✅ **Modern PHP 8.4+** - Typed properties, readonly classes, enums, and constructor property promotion
- ✅ **Full DOI Management** - Create, read, update, delete, and search DOI records
- ✅ **DataCite Events** - Query and retrieve usage events for DOIs
- ✅ **Advanced Query Builder** - Fluent interface for complex searches with boolean logic
- ✅ **Typed DTOs** - Fully typed data transfer objects for all API responses
- ✅ **Built on Saloon** - Powerful HTTP client with mocking and testing support
- ✅ **Framework Agnostic** - Works with any PHP framework or standalone
- ✅ **Comprehensive Tests** - Full test coverage with Pest PHP

---

Installation
------------

[](#installation)

```
composer require vincentauger/datacite-php-sdk
```

**Requirements:**

- PHP 8.4+
- Composer

---

Quick Start
-----------

[](#quick-start)

### Initialize the Client

[](#initialize-the-client)

#### Public API (Read-Only)

[](#public-api-read-only)

```
use VincentAuger\DataCiteSdk\DataCite;

// No credentials needed for public read-only access
$datacite = new DataCite();
```

#### Member API (Full Access)

[](#member-api-full-access)

```
use VincentAuger\DataCiteSdk\DataCite;

// Credentials required for create/update/delete operations
$datacite = new DataCite(
    username: 'your-repository-id',
    password: 'your-repository-password',
    mailto: 'your-email@example.com'  // Optional but recommended
);
```

---

Usage Examples
--------------

[](#usage-examples)

### Get a Single DOI

[](#get-a-single-doi)

**Quick way (convenience method):**

```
// Simple one-liner for basic operations
$response = $datacite->getDOI('10.5438/4k3m-nyvg');
$doi = $response->dto();

echo $doi->data->attributes->titles[0]->title;
echo $doi->data->attributes->creators[0]->name;
echo $doi->data->attributes->publicationYear;
```

**Advanced way (using request objects):**

```
use VincentAuger\DataCiteSdk\Requests\DOIs\GetDOI;

// Use request objects when you need more control
$request = new GetDOI('10.5438/4k3m-nyvg');
$response = $datacite->send($request);
$doi = $response->dto();
```

### List DOIs

[](#list-dois)

```
use VincentAuger\DataCiteSdk\Requests\DOIs\ListDOIs;
use VincentAuger\DataCiteSdk\Enums\SortOption;

$request = (new ListDOIs)
    ->withPageSize(25)
    ->withSortDesc(SortOption::CREATED);

$response = $datacite->send($request);
$results = $response->dto();

foreach ($results->data as $doi) {
    echo "{$doi->id}: {$doi->attributes->titles[0]->title}\n";
}

echo "Total: {$results->meta->total}\n";
```

### Search DOIs with Query Builder

[](#search-dois-with-query-builder)

```
use VincentAuger\DataCiteSdk\Query\QueryBuilder;
use VincentAuger\DataCiteSdk\Enums\QueryField;
use VincentAuger\DataCiteSdk\Requests\DOIs\ListDOIs;

$query = (new QueryBuilder)
    ->whereEquals(QueryField::PUBLICATION_YEAR, '2023')
    ->whereContains(QueryField::TITLES_TITLE, 'climate')
    ->whereExists(QueryField::FUNDING_REFERENCES_FUNDER_NAME);

$request = (new ListDOIs)->withQuery($query);
$response = $datacite->send($request);
$results = $response->dto();
```

### Create a DOI

[](#create-a-doi)

```
use VincentAuger\DataCiteSdk\Data\CreateDOIInput;
use VincentAuger\DataCiteSdk\Data\Metadata\Creator;
use VincentAuger\DataCiteSdk\Data\Metadata\Title;
use VincentAuger\DataCiteSdk\Data\Metadata\ResourceType;
use VincentAuger\DataCiteSdk\Enums\ResourceTypeGeneral;
use VincentAuger\DataCiteSdk\Enums\DOIEvent;

$input = new CreateDOIInput(
    doi: '10.5438/example-doi',
    url: 'https://example.com/dataset',
    titles: [new Title('My Dataset Title')],
    creators: [new Creator(name: 'Smith, John')],
    publisher: new PublisherData(name: 'Example Publisher'),
    publicationYear: 2025,
    types: new ResourceType(
        resourceTypeGeneral: ResourceTypeGeneral::DATASET,
        resourceType: 'Dataset'
    ),
    event: DOIEvent::PUBLISH  // Optional: publish, register, or hide
);

// Quick way (convenience method)
$response = $datacite->createDOI($input);
$doi = $response->dto();

// Or use request object for more control
$request = new CreateDOI($input);
$response = $datacite->send($request);
```

### Update a DOI

[](#update-a-doi)

```
use VincentAuger\DataCiteSdk\Data\UpdateDOIInput;

$input = new UpdateDOIInput(
    doi: '10.5438/example-doi',
    titles: [new Title('Updated Title')],
    // ... other updated fields
);

// Quick way (convenience method)
$response = $datacite->updateDOI('10.5438/example-doi', $input);

// Or use request object
$request = new UpdateDOI('10.5438/example-doi', $input);
$response = $datacite->send($request);
```

### Delete a DOI

[](#delete-a-doi)

```
// Only works for draft DOIs
$response = $datacite->deleteDOI('10.5438/draft-doi');

// Or use request object
$request = new DeleteDOI('10.5438/draft-doi');
$response = $datacite->send($request);
```

### Get DOI Activities

[](#get-doi-activities)

```
// Quick way (convenience method)
$response = $datacite->getDOIActivities('10.5438/4k3m-nyvg');
$activities = $response->dto();

foreach ($activities->data as $activity) {
    echo "{$activity->attributes->action} at {$activity->attributes->createdAt}\n";
}

// Or use request object
use VincentAuger\DataCiteSdk\Requests\DOIs\GetDOIActivities;

$request = new GetDOIActivities('10.5438/4k3m-nyvg');
$response = $datacite->send($request);
```

### List Events

[](#list-events)

```
use VincentAuger\DataCiteSdk\Requests\Events\ListEvents;
use VincentAuger\DataCiteSdk\Enums\EventSortOption;
use VincentAuger\DataCiteSdk\Enums\EventSource;

$request = (new ListEvents)
    ->withDoiId('10.5438/4k3m-nyvg')
    ->withSource(EventSource::CROSSREF)
    ->withYearMonth(2023, 6)
    ->withSortDesc(EventSortOption::TOTAL)
    ->withPageSize(25);

$response = $datacite->send($request);
$events = $response->dto();

foreach ($events->data as $event) {
    echo "{$event->id}: {$event->attributes->total} occurrences\n";
}
```

### Get a Single Event

[](#get-a-single-event)

```
// Quick way (convenience method)
$response = $datacite->getEvent('event-id-here');
$event = $response->dto();

// Or use request object
use VincentAuger\DataCiteSdk\Requests\Events\GetEvent;

$request = new GetEvent('event-id-here');
$response = $datacite->send($request);
```

---

Convenience Methods
-------------------

[](#convenience-methods)

The SDK provides convenient shorthand methods for common operations:

```
// System
$datacite->heartbeat(): bool

// DOIs
$datacite->getDOI(string $doi): Response
$datacite->getDOIActivities(string $doi): Response
$datacite->createDOI(CreateDOIInput $input): Response
$datacite->updateDOI(string $doi, UpdateDOIInput $input): Response
$datacite->deleteDOI(string $doi): Response

// Events
$datacite->getEvent(string $eventId): Response
```

**When to use convenience methods:**

- ✅ Quick, simple operations
- ✅ Getting started with the SDK
- ✅ Straightforward single-resource retrieval

**When to use request objects:**

- ✅ Complex queries with filters
- ✅ Pagination and sorting
- ✅ Using the QueryBuilder
- ✅ Need to customize request behavior

---

Advanced Features
-----------------

[](#advanced-features)

### Query Builder

[](#query-builder)

Build complex search queries with a fluent interface. See [docs/QueryBuilder.md](docs/QueryBuilder.md) for full documentation.

```
use VincentAuger\DataCiteSdk\Query\QueryBuilder;
use VincentAuger\DataCiteSdk\Enums\QueryField;

$query = (new QueryBuilder)
    ->whereEquals(QueryField::PUBLICATION_YEAR, '2023')
    ->whereOr(function (QueryBuilder $builder) {
        $builder
            ->whereContains(QueryField::TITLES_TITLE, 'climate')
            ->whereContains(QueryField::TITLES_TITLE, 'weather');
    })
    ->whereExists(QueryField::CREATORS_NAME_IDENTIFIER);
```

**Available Methods:**

- `whereEquals()`, `whereNotEquals()` - Exact matching
- `whereContains()` - Case-insensitive contains search
- `whereStartsWith()`, `whereEndsWith()` - Wildcard prefix/suffix
- `whereExists()`, `whereNotExists()` - Field presence checks
- `whereIn()`, `whereNotIn()` - Multiple value matching
- `whereAnd()`, `whereOr()` - Boolean logic grouping
- `whereExact()` - Quoted exact match for phrases

### Sorting and Filtering

[](#sorting-and-filtering)

Apply sorting, filtering, and pagination to list requests. See [docs/sorting-and-filtering.md](docs/sorting-and-filtering.md) for examples.

```
use VincentAuger\DataCiteSdk\Enums\SortOption;

$request = (new ListDOIs)
    ->withProviderId('cern')
    ->withClientId('cern.zenodo')
    ->withCreated('2023-01-01,2023-12-31')  // Date range
    ->withHasPerson(true)
    ->withHasFundingReference(true)
    ->withSortDesc(SortOption::CREATED)
    ->withPageSize(50)
    ->withPage(2)
    ->withAffiliation()  // Include additional data
    ->withPublisher();
```

**DOI Sort Options:**

- `RELEVANCE` - Search relevance (default)
- `NAME` - DOI name
- `CREATED` - Creation date
- `UPDATED` - Last updated
- `PUBLISHED` - Publication date
- `REGISTERED` - Registration date

**Event Sort Options:**

- `RELEVANCE` - Search relevance
- `OBJ_ID` - Object ID
- `TOTAL` - Total occurrences
- `CREATED` - Creation date
- `UPDATED` - Last updated

---

Working with DTOs and Type Hints
--------------------------------

[](#working-with-dtos-and-type-hints)

All API responses return fully typed Data Transfer Objects (DTOs) for type safety and IDE autocomplete. However, due to how Saloon creates DTOs, you may lose type information when calling `->dto()`.

### Getting Proper Type Hints

[](#getting-proper-type-hints)

**Option 1: Use PHPDoc annotation (Recommended)**

```
use VincentAuger\DataCiteSdk\Data\DOIData;

/** @var DOIData $doi */
$doi = $response->dto();

// Now you get full IDE autocomplete and type checking
$title = $doi->data->attributes->titles[0]->title;
```

**Option 2: Use `createDtoFromResponse()` directly**

```
$request = new GetDOI('10.5438/4k3m-nyvg');
$response = $datacite->send($request);

// This method returns the correct type automatically
$doi = $request->createDtoFromResponse($response);
```

### Available DTOs

[](#available-dtos)

Request TypeDTO ClassDescription`GetDOI``DOIData`Single DOI response`ListDOIs``ListDOIData`Paginated DOI list`CreateDOI``DOIData`Created DOI response`UpdateDOI``DOIData`Updated DOI response`GetDOIActivities``DOIActivitiesData`DOI activity log`GetEvent``EventData`Single event response`ListEvents``ListEventData`Paginated event list**Example with proper typing:**

```
use VincentAuger\DataCiteSdk\Data\DOIData;
use VincentAuger\DataCiteSdk\Data\ListDOIData;

// Single DOI
/** @var DOIData $doi */
$doi = $datacite->getDOI('10.5438/0012')->dto();

// List of DOIs
/** @var ListDOIData $results */
$results = $datacite->send(new ListDOIs)->dto();

foreach ($results->data as $doiItem) {
    // Full autocomplete available
    echo $doiItem->attributes->titles[0]->title;
}
```

---

Configuration
-------------

[](#configuration)

### Client Options

[](#client-options)

ParameterTypeDefaultDescription`baseUrl``string``https://api.datacite.org`DataCite API base URL`username``string|null``null`Repository ID (required for member API)`password``string|null``null`Repository password (required for member API)`mailto``string|null``null`Email for User-Agent header (optional)### Authentication

[](#authentication)

The SDK supports two access levels:

1. **Public API** (default) - Read-only access to DOI metadata and events (no credentials needed)
2. **Member API** - Full access including create/update/delete (requires credentials)

```
// Public API - read-only
$datacite = new DataCite();

// Member API - full access
$datacite = new DataCite(
    apiVersion: ApiVersion::MEMBER,
    username: 'your-repository-id',
    password: 'your-repository-password'
);
```

Endpoints that modify data (POST, PUT, DELETE) use the `RequiresMemberAuth` trait and will throw a `RuntimeException` if you attempt these operations without proper authentication.

---

API Coverage
------------

[](#api-coverage)

### System

[](#system)

- ✅ `GET /heartbeat` - Check API status

### DOIs

[](#dois)

- ✅ `GET /dois` - List DOIs with advanced filtering
- ✅ `GET /dois/{id}` - Get a single DOI
- ✅ `POST /dois` - Create a new DOI (member only)
- ✅ `PUT /dois/{id}` - Update a DOI (member only)
- ✅ `DELETE /dois/{id}` - Delete a draft DOI (member only)
- ✅ `GET /dois/{id}/activities` - Get DOI activity log

### Events

[](#events)

- ✅ `GET /events` - List events with filtering
- ✅ `GET /events/{id}` - Get a single event

---

Contributing
------------

[](#contributing)

Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for:

- Development environment setup
- Coding standards and guidelines
- Testing requirements
- Pull request process

---

Documentation
-------------

[](#documentation)

- **[QueryBuilder.md](docs/QueryBuilder.md)** - Complete query builder reference with examples
- **[sorting-and-filtering.md](docs/sorting-and-filtering.md)** - Sorting, filtering, and pagination examples

---

License
-------

[](#license)

MIT License — see [LICENSE.md](LICENSE.md) for details.

---

Disclaimer
----------

[](#disclaimer)

This SDK is **unofficial** and not affiliated with [DataCite](https://datacite.org/).

- Use at your own risk
- Respect DataCite API rate limits and terms of service
- Ensure proper authentication and security for member API credentials
- Always test in a non-production environment first

For official DataCite documentation, visit [support.datacite.org/docs](https://support.datacite.org/docs/api).

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance90

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~28 days

Recently: every ~36 days

Total

6

Last Release

49d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/86c5e11f0405a38fa5411ed2c3445fa72b850fcb21f2ecb7c91ad1d4776327fd?d=identicon)[vincentauger](/maintainers/vincentauger)

---

Top Contributors

[![vincentauger](https://avatars.githubusercontent.com/u/19717710?v=4)](https://github.com/vincentauger "vincentauger (49 commits)")

---

Tags

dataciteopen-sciencephpphpapisdkpackagedataciteopen science

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/vincentauger-datacite-php-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/vincentauger-datacite-php-sdk/health.svg)](https://phpackages.com/packages/vincentauger-datacite-php-sdk)
```

###  Alternatives

[jstolpe/instagram-graph-api-php-sdk

Instagram Graph API PHP SDK

13998.4k2](/packages/jstolpe-instagram-graph-api-php-sdk)[musheabdulhakim/gohighlevel-php

php sdk for gohighlevel api

151.1k](/packages/musheabdulhakim-gohighlevel-php)[clever/clever-php

231.6k](/packages/clever-clever-php)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
