Create an Entry

Create an Entry

This endpoint creates a new content entry in a specified collection.

Endpoint

[POST]

/{collection_slug}

Permissions

This endpoint requires a token with the create ability.

Path Parameters

NameRequiredDescription
collection_slugYesThe unique slug of the collection.

Headers

NameRequiredDescription
AcceptYesSpecifies the response content type. Must be application/json.
AuthorizationYesRequired. Must be a Bearer token with create scope.
project-idYesThe unique identifier for the project.

Body Parameters

On create, state: "published" publishes immediately (version 1). Omitting state or using draft leaves the entry unpublished until you call Publish.

The request body should be a JSON object containing the following keys:

NameTypeRequiredDescription
dataobjectYesAn object where keys are the field names and values are the content for each field.
statestringNoPublication state on create: published or draft (default). published mints version 1.
localestringNoThe locale code for the content (e.g., en-US).

Relation and Media Reference Rules

  • Relation and media fields accept entry/asset UUIDs (and numeric IDs when enabled by your setup).
  • Every referenced entry/asset must belong to the same project as the request.
  • Relation fields must also match the relation field's configured target collection.
  • Invalid references return 422 validation errors under data.<field_name>.

data Object Example

{
    "data": {
        "title": "My New Post",
        "slug": "my-new-post-slug",
        "author": "e3a4b1c2-d5e6-f7g8-h9i0-j1k2l3m4n5o6", // UUID for a relation
        "tags": [
            { "value": "API" },
            { "value": "Tech" }
        ] // Example for a repeatable text field
    },
    "state": "published",
    "locale": "en"
}

Example Requests

import { createClient } from '@elmapicms/js-sdk';
 
const client = createClient({
  baseUrl: 'https://your-domain.com/api',
  apiKey: 'YOUR_API_TOKEN',
  projectId: 'YOUR_PROJECT_UUID',
});
 
// Create a new entry
const newEntry = await client.content.create('blog-posts', {
  locale: 'en',
  state: 'draft',
  data: {
    title: 'API Best Practices',
    slug: 'api-best-practices'
  }
});
 
// Create a published entry
const publishedEntry = await client.content.create('blog-posts', {
  locale: 'en',
  state: 'published',
  published_at: '2024-01-01T00:00:00Z',
  data: {
    title: 'My Published Post',
    slug: 'my-published-post'
  }
});
const collectionSlug = 'blog-posts';
const newEntry = {
    data: {
        title: 'API Best Practices',
        slug: 'api-best-practices'
    },
    state: 'draft'
};
 
axios.post(`https://your-domain.com/api/${collectionSlug}`, newEntry, {
    headers: {
        'Accept': 'application/json',
        'Authorization': 'Bearer YOUR_API_TOKEN', // Required - must have 'create' ability
        'project-id': 'YOUR_PROJECT_UUID'
    }
});
use Illuminate\Support\Facades\Http;
 
$collectionSlug = 'blog-posts';
$newEntry = [
    'data' => [
        'title' => 'API Best Practices',
        'slug' => 'api-best-practices'
    ],
    'state' => 'draft'
];
 
$response = Http::withToken('YOUR_API_TOKEN')->withHeaders([
    'Accept' => 'application/json',
    'project-id' => 'YOUR_PROJECT_UUID'
])->post("https://your-domain.com/api/{$collectionSlug}", $newEntry);
import React, { useState } from 'react';
 
function CreateEntryForm({ collectionSlug }) {
  const [title, setTitle] = useState('');
  const [slug, setSlug] = useState('');
 
  const handleSubmit = async (event) => {
    event.preventDefault();
    try {
      const response = await fetch(`https://your-domain.com/api/${collectionSlug}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
          'Authorization': 'Bearer YOUR_API_TOKEN', // Required - must have 'create' ability
          'project-id': 'YOUR_PROJECT_UUID'
        },
        body: JSON.stringify({
          data: { title, slug },
          state: 'draft'
        })
      });
 
      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.message || 'Failed to create entry');
      }
 
      const createdEntry = await response.json();
      console.log('Entry created:', createdEntry);
    } catch (error) {
      console.error('Failed to create entry:', error);
    }
  };
 
  return (
    <form onSubmit={handleSubmit}>
      <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} placeholder="Title" required />
      <input type="text" value={slug} onChange={(e) => setSlug(e.target.value)} placeholder="Slug" required />
      <button type="submit">Create Entry</button>
    </form>
  );
}
<template>
  <form @submit.prevent="createEntry">
    <input v-model="title" placeholder="Title" required />
    <input v-model="slug" placeholder="Slug" required />
    <button type="submit">Create Entry</button>
  </form>
</template>
 
<script setup>
import { ref } from 'vue';
 
const props = defineProps({
  collectionSlug: { type: String, required: true }
});
 
const title = ref('');
const slug = ref('');
 
const createEntry = async () => {
  try {
    const response = await fetch(`https://your-domain.com/api/${props.collectionSlug}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': 'Bearer YOUR_API_TOKEN', // Required - must have 'create' ability
        'project-id': 'YOUR_PROJECT_UUID'
      },
      body: JSON.stringify({
        data: {
          title: title.value,
          slug: slug.value,
        },
        state: 'draft'
      })
    });
 
    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData.message || 'Failed to create entry');
    }
 
    const createdEntry = await response.json();
    console.log('Entry created:', createdEntry);
  } catch (error) {
    console.error('Failed to create entry:', error);
  }
};
</script>
curl -X POST "https://your-domain.com/api/blog-posts" \
     -H "Accept: application/json" \
     -H "Authorization: Bearer YOUR_API_TOKEN" \
     -H "project-id: YOUR_PROJECT_UUID" \
     -H "Content-Type: application/json" \
     -d '{
         "data": {
             "title": "API Best Practices",
             "slug": "api-best-practices"
         },
         "state": "draft"
     }'

Responses

201: Created

Returns the newly created content entry object.

{
    "data": {
        "uuid": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
        "locale": "en",
        "published_at": null,
        "fields": {
            "title": "API Best Practices",
            "slug": "api-best-practices"
        }
    }
}

403: Forbidden

Returned if the API token does not have the create ability.

{
    "message": "API token doesn't have the right abilities!"
}

422: Unprocessable Entity

Returned for validation errors, such as a missing required field, a non-unique value for a unique field, invalid relation/media references, or attempting to create an entry in a singleton collection that already has one.

{
    "message": "The slug field is required.",
    "errors": {
        "data.slug": [
            "The slug field is required."
        ],
        "data.gallery": [
            "One or more media references are invalid for this project."
        ]
    }
}

Search documentation

Find guides and reference pages