Getting Started

First Steps

Create your first ZineCore2 records via the API

This tutorial walks you through creating your first zine catalog using the ZineCore2 API. You'll create an agent (creator), a repository, a zine, and a holding record.

Prerequisites

  • ✅ ZineCore2 server installed and running
  • ✅ Superuser account created
  • ✅ API accessible at http://localhost:8000

Overview

We'll create records in this order:

  1. Agent (creator of the zine)
  2. Repository (where the zine is held)
  3. Zine (the bibliographic record)
  4. Holding (linking the zine to the repository)

This order ensures that when we create the zine, we can reference the agent by ID, and when we create the holding, we can reference both the zine and repository.


Step 1: Get an API Token

The API requires authentication for write operations.

Option A: Via curl

curl -X POST http://localhost:8000/api/auth/token/ \
  -H "Content-Type: application/json" \
  -d '{"username": "admin", "password": "yourpassword"}'

Response:

{
  "token": "abc123def456..."
}

Save this token — you'll use it for all write operations.

Option B: Via Browsable API

  1. Visit http://localhost:8000/api/
  2. Click "Log in" in the top right
  3. Enter your superuser credentials
  4. You're now authenticated for browsable API use

Step 2: Create an Agent (Creator)

Let's create an agent record for the zine creator.

Using curl

curl -X POST http://localhost:8000/api/agents/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Token YOUR_TOKEN_HERE" \
  -d '{
    "id": "agent_judith_arcana",
    "kind": "Person",
    "display_name": "Judith Arcana",
    "pronouns": ["she/her"],
    "biography": "Feminist writer and activist, creator of reproductive rights zines.",
    "website": "https://juditharcana.com",
    "roles": ["creator", "editor"],
    "public": true
  }'

Using Python

import requests

API_BASE = "http://localhost:8000/api"
TOKEN = "YOUR_TOKEN_HERE"
headers = {
    "Authorization": f"Token {TOKEN}",
    "Content-Type": "application/json"
}

agent_data = {
    "id": "agent_judith_arcana",
    "kind": "Person",
    "display_name": "Judith Arcana",
    "pronouns": ["she/her"],
    "biography": "Feminist writer and activist, creator of reproductive rights zines.",
    "website": "https://juditharcana.com",
    "roles": ["creator", "editor"],
    "public": True
}

response = requests.post(
    f"{API_BASE}/agents/",
    headers=headers,
    json=agent_data
)

print(response.status_code)  # Should be 201 Created
agent = response.json()
print(f"Created agent: {agent['display_name']}")

Using JavaScript

const API_BASE = "http://localhost:8000/api";
const TOKEN = "YOUR_TOKEN_HERE";

const agentData = {
  id: "agent_judith_arcana",
  kind: "Person",
  display_name: "Judith Arcana",
  pronouns: ["she/her"],
  biography: "Feminist writer and activist, creator of reproductive rights zines.",
  website: "https://juditharcana.com",
  roles: ["creator", "editor"],
  public: true
};

const response = await fetch(`${API_BASE}/agents/`, {
  method: "POST",
  headers: {
    "Authorization": `Token ${TOKEN}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify(agentData)
});

const agent = await response.json();
console.log(`Created agent: ${agent.display_name}`);

Expected Response (201 Created):

{
  "id": "agent_judith_arcana",
  "kind": "Person",
  "display_name": "Judith Arcana",
  "pronouns": ["she/her"],
  "biography": "Feminist writer and activist, creator of reproductive rights zines.",
  "website": "https://juditharcana.com",
  "roles": ["creator", "editor"],
  "public": true,
  "created_at": "2024-02-25T10:30:00Z",
  "updated_at": "2024-02-25T10:30:00Z"
}

Step 3: Create a Repository

Now create a repository record for where the zine will be held.

curl -X POST http://localhost:8000/api/repositories/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Token YOUR_TOKEN_HERE" \
  -d '{
    "id": "repo_my_personal_collection",
    "repository_name": "My Personal Zine Collection",
    "repository_kind": "personal-collection",
    "description": "Personal collection of feminist and queer zines.",
    "city": "Seattle",
    "region": "WA",
    "country": "US",
    "established": "2020",
    "status": "active"
  }'

Expected Response (201 Created):

{
  "id": "repo_my_personal_collection",
  "repository_name": "My Personal Zine Collection",
  "repository_kind": "personal-collection",
  "description": "Personal collection of feminist and queer zines.",
  "city": "Seattle",
  "region": "WA",
  "country": "US",
  "established": "2020",
  "status": "active",
  "created_at": "2024-02-25T10:31:00Z"
}

Step 4: Create a Zine

Now create the bibliographic record for a zine, referencing the agent we created:

curl -X POST http://localhost:8000/api/zines/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Token YOUR_TOKEN_HERE" \
  -d '{
    "id": "zine_mutate_3_1st",
    "title": "Mutate Zine #3: Abortion Stories",
    "series_title": ["Mutate Zine"],
    "issue_designation": "#3",
    "creator": ["agent_judith_arcana"],
    "subject": ["feminism", "reproductive-rights", "personal-narratives"],
    "genre": ["personal-zine"],
    "date": ["2024"],
    "language": ["en"],
    "rights": ["cc-by-4.0"],
    "abstract": "Personal narratives and essays about reproductive rights and abortion access.",
    "format": ["Photocopy"],
    "number_of_pages": "32"
  }'

Expected Response (201 Created):

{
  "id": "zine_mutate_3_1st",
  "title": "Mutate Zine #3: Abortion Stories",
  "series_title": ["Mutate Zine"],
  "issue_designation": "#3",
  "creator": [
    {
      "id": "agent_judith_arcana",
      "display_name": "Judith Arcana",
      "kind": "Person"
    }
  ],
  "subject": ["feminism", "reproductive-rights", "personal-narratives"],
  "genre": ["personal-zine"],
  "date": ["2024"],
  "language": ["en"],
  "rights": ["cc-by-4.0"],
  "abstract": "Personal narratives and essays about reproductive rights and abortion access.",
  "format": ["Photocopy"],
  "number_of_pages": "32",
  "created_at": "2024-02-25T10:32:00Z"
}

Note: The response resolves the creator field to full agent objects (read serializer), but you only need to provide agent IDs when creating (write serializer).


Step 5: Create a Holding

Finally, create a holding record linking the zine to your repository:

curl -X POST http://localhost:8000/api/holdings/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Token YOUR_TOKEN_HERE" \
  -d '{
    "id": "holding_my_mutate_3",
    "repository_id": "repo_my_personal_collection",
    "zine_id": "zine_mutate_3_1st",
    "location": "Bookshelf 2 - Feminist Zines",
    "condition": "Excellent",
    "copy_count": 1,
    "access_status": "personal-use",
    "notes": ["Acquired at Ladyfest 2024"]
  }'

Expected Response (201 Created):

{
  "id": "holding_my_mutate_3",
  "repository": {
    "id": "repo_my_personal_collection",
    "repository_name": "My Personal Zine Collection"
  },
  "zine": {
    "id": "zine_mutate_3_1st",
    "title": "Mutate Zine #3: Abortion Stories"
  },
  "location": "Bookshelf 2 - Feminist Zines",
  "condition": "Excellent",
  "copy_count": 1,
  "access_status": "personal-use",
  "notes": ["Acquired at Ladyfest 2024"],
  "created_at": "2024-02-25T10:33:00Z"
}

Step 6: Retrieve Your Records

Now that you've created records, retrieve them via the API.

Get All Zines

curl http://localhost:8000/api/zines/

No authentication needed for read operations!

Get Specific Zine

curl http://localhost:8000/api/zines/zine_mutate_3_1st/

Get Zine in Different Formats

JSON-LD:

curl -H "Accept: application/ld+json" \
  http://localhost:8000/api/zines/zine_mutate_3_1st/

CSV:

curl -H "Accept: text/csv" \
  http://localhost:8000/api/zines/

BibTeX:

curl -H "Accept: application/x-bibtex" \
  http://localhost:8000/api/zines/zine_mutate_3_1st/

Step 7: Update a Record

Update the zine to add more information:

curl -X PATCH http://localhost:8000/api/zines/zine_mutate_3_1st/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Token YOUR_TOKEN_HERE" \
  -d '{
    "publisher": ["Feminist Press Collective"],
    "place_of_publication": ["Seattle, WA"]
  }'

PATCH updates only the fields you provide. PUT replaces the entire record.


Step 8: Search and Filter

Filter Zines by Subject

curl "http://localhost:8000/api/zines/?subject=feminism"

Filter by Genre

curl "http://localhost:8000/api/zines/?genre=personal-zine"

Filter by Creator

curl "http://localhost:8000/api/zines/?creator=agent_judith_arcana"

Search by Title

curl "http://localhost:8000/api/zines/?search=Mutate"

Step 9: Browse via Admin Interface

Visit the Django admin at http://localhost:8000/admin/ to:

  • View all records in a user-friendly interface
  • Edit records with form validation
  • Bulk delete or update records
  • See relationships between profiles

Complete Example Script

Here's a Python script that creates all four records:

import requests

API_BASE = "http://localhost:8000/api"
TOKEN = "YOUR_TOKEN_HERE"

headers = {
    "Authorization": f"Token {TOKEN}",
    "Content-Type": "application/json"
}

# 1. Create Agent
agent = requests.post(f"{API_BASE}/agents/", headers=headers, json={
    "id": "agent_judith_arcana",
    "kind": "Person",
    "display_name": "Judith Arcana",
    "public": True
}).json()
print(f"✓ Created agent: {agent['display_name']}")

# 2. Create Repository
repo = requests.post(f"{API_BASE}/repositories/", headers=headers, json={
    "id": "repo_my_collection",
    "repository_name": "My Personal Collection",
    "repository_kind": "personal-collection",
    "country": "US"
}).json()
print(f"✓ Created repository: {repo['repository_name']}")

# 3. Create Zine
zine = requests.post(f"{API_BASE}/zines/", headers=headers, json={
    "id": "zine_mutate_3",
    "title": "Mutate Zine #3",
    "creator": ["agent_judith_arcana"],
    "subject": ["feminism"],
    "genre": ["personal-zine"],
    "date": ["2024"],
    "language": ["en"],
    "rights": ["cc-by-4.0"]
}).json()
print(f"✓ Created zine: {zine['title']}")

# 4. Create Holding
holding = requests.post(f"{API_BASE}/holdings/", headers=headers, json={
    "id": "holding_001",
    "repository_id": "repo_my_collection",
    "zine_id": "zine_mutate_3",
    "condition": "Excellent"
}).json()
print(f"✓ Created holding at {holding['repository']['repository_name']}")

print("\n✅ Catalog created successfully!")

Validation Errors

If you get validation errors, the API will return details:

Example Error Response (400 Bad Request):

{
  "title": ["This field is required."],
  "creator": ["This field is required."],
  "subject": ["This field must contain at least one item."]
}

Fix the issues and resubmit.


Next Steps

Now that you've created your first records:

Congratulations! You've successfully created your first ZineCore2 catalog. Continue to the API Reference to explore all available endpoints.
Copyright ©2026 ZineCore2 Contributors,