{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"d76f92ef-619e-4b9d-94fa-b6f3e152161c","name":"Radmin API","description":"# Radmin API\n\nA hands-on Postman collection for testing radmin's JSON API across development, staging, and production. Open the shared collection in Postman, select the right environment, add your own radmin credentials, create a token, then run the examples.\n\n> Production writes are real writes. Check `DS-METRO-ID` before creating events, importing queue items, approving queue work, or flushing queues.\n\n## 🚀 Fast Start\n\n1. Open the shared `Radmin API` collection in Postman.\n2. Select the environment you want to test against: `Radmin API Development`, `Radmin API Staging`, or `Radmin API Production`.\n3. Fill these environment variables in your selected Postman environment:\n   - `api_email`: the same email address you use for radmin.\n   - `api_password`: the same password you use for radmin.\n   - `metro_id`: the active metro/property id for the request context.\n4. Run `Authentication / Create Token`.\n5. The token response stores `jwt` and `user_id` in your selected environment.\n6. Run the API examples. Requests that operate in a metro send `DS-METRO-ID: {{metro_id}}`.\n\n## 🌎 Environments\n\n| Environment | `radmin_url` | Use for |\n|---|---|---|\n| Development | `https://radmin.dothebay.baw` | Local development and Docker/Caddy testing. |\n| Staging | `https://stadmin.dostuffmedia.com` | Pre-production smoke testing before deploy. |\n| Production | `https://radmin.dostuffmedia.com` | Real radmin data. Use deliberately. |\n\nEach user should store their own `api_email` and `api_password` in their Postman environment. The production environment is safe to use for testing reads, but write requests create or update real radmin data.\n\n## 🗂️ Collections\n\nCollections let radmin build reusable groups of events, venues, artists, tastemakers, and curated picks for apps and pages. Use them when you need to create or update the sets of content that a frontend experience will display.\n\nUse the [Collections folder](#collections) for the concrete requests. A collection group owns an ordered list of collections. Collections can be automatic (`all_events`, `venue`, `promo_user`, `tastemaker`, `band`, `query`) or `curated`. Curated collection items are managed through `collection_items_attributes` on collection create/update payloads; there is no standalone collection-item endpoint in this API collection.\n\n## 🔐 Auth\n\n- `POST /api/tokens` uses radmin email/password validation and returns the existing radmin JWT shape.\n- The collection sends `Authorization: Bearer {{jwt}}` automatically after token creation.\n- Metro context belongs in `DS-METRO-ID`, not request bodies.\n- Missing or invalid bearer tokens return JSON `401`.\n\n## 📄 Pagination\n\n- Most CRUD list endpoints accept `page` and `per_page`. Collection group endpoints currently return arrays because they follow the existing radmin-v2 collection API shape.\n- Default page size is 50; maximum is 100.\n- Normal CRUD list responses include `current_page`, `per_page`, `total_pages`, and `total_count`.\n- Pending and duplicate queue responses skip expensive total counts and return `current_page`, `per_page`, and `next_page`.\n\n## 🎟️ Events And Queues\n\nRadmin has two event creation paths: direct event CRUD for approved events, and event imports for review queues. Pick the path that matches the workflow you are automating.\n\n### ✅ Create Approved Events\n\nUse `POST /api/events` when the event is ready to go live. This is normal CRUD creation and creates an approved event directly in radmin.\n\n### 🔎 Preview Duplicate Handling\n\nUse `POST /api/event_dupe_checks` as a dry run before importing scraped or external data. It accepts event-shaped data, creates nothing, and returns the duplicate gate result radmin would use: ignored event, obvious duplicate, obvious repeating duplicate, obvious ongoing duplicate, pending replacement, or potential duplicate.\n\n### 🧾 Import Events For Review\n\nUse `POST /api/event_imports` when you want radmin to create unapproved review work. With no `queue` value, or with `queue: \"auto\"`, radmin behaves like the scraper importer: obvious duplicates are skipped, normal candidates enter pending review, and potential duplicates enter duplicate review.\n\n### 📥 Force Pending Review\n\nSet `queue: \"pending\"` on `POST /api/event_imports` to force a normal pending queue item. This does not create `EventDupe` records because normal pending review does not need comparison targets.\n\n### 🧬 Force Duplicate Review\n\nSet `queue: \"duplicate\"` on `POST /api/event_imports` to create a duplicate queue item. If you pass `potential_dupe_id` or `potential_dupe_ids`, radmin uses those approved events as comparison targets. If you omit them, radmin generates potential dupes from the posted event using its scraper duplicate logic. If no approved comparison event can be found, the request is rejected instead of creating broken duplicate state.\n\n### 📚 Review Queue Items\n\nUse `GET /api/event_queues/pending` to list unapproved non-duplicate pending events. Use `GET /api/event_queues/duplicates` to list unapproved duplicate-review events and their comparison matches. Queue list responses are paginated and intentionally avoid total counts because these queues can be slow. Follow `pagination.next_page` until it is empty.\n\n### 🔒 Approve Or Flush Queues\n\nQueue approval and flush endpoints use the same Redis locks as radmin. If a flush is already running, list and flush requests return HTTP `423` with `error: queue_locked`. Treat that as \"try again later,\" not as a failed import.\n\n## 🧪 Common Workflows\n\n- Grant Event Editor access: list roles with `GET /api/roles`, find or create the user with the Users requests, then create a user permission with `POST /api/users/:user_id/permissions`. Event Editor is role id `8`.\n- Add an artist: use `POST /api/artists`. You can include `cover_image_url` to pull the image by URL.\n- Add an approved event with images: use `POST /api/events` with `venue_id`, `category_id`, optional `band_ids`, and image URLs such as `cover_image_url`, `poster_image_url`, or `share_image_url`.\n\n## 🛡️ Rate Limits\n\n- `/api/tokens` is throttled by IP.\n- API resource routes are throttled by SHA256 fingerprint of the raw `Authorization` header.\n- Default limits are 5,000 requests per 5 minutes and 300 write requests per 5 minutes per auth header. That write limit is roughly one write per second per token.\n- Throttled responses return HTTP `429` with `{ \"error\": \"rate_limited\" }` plus `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` headers.","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":false,"owner":"2966202","team":417167,"collectionId":"d76f92ef-619e-4b9d-94fa-b6f3e152161c","publishedId":"2sBXwtr9qX","public":true,"publicUrl":"https://radmin-api-docs.dostuffmedia.com","privateUrl":"https://go.postman.co/documentation/2966202-d76f92ef-619e-4b9d-94fa-b6f3e152161c","customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"documentationLayout":"classic-double-column","customisation":{"metaTags":[{"name":"description","value":""},{"name":"title","value":""}],"appearance":{"default":"dark","themes":[{"name":"dark","logo":null,"colors":{"top-bar":"212121","right-sidebar":"303030","highlight":"FF6C37"}},{"name":"light","logo":null,"colors":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"}}]}},"version":"8.12.3","publishDate":"2026-06-17T18:41:49.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{"title":"","description":""},"logos":{"logoLight":null,"logoDark":null}},"statusCode":200},"environments":[],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/370d698e3a9873fdef925775704a6b533e83a4b4f56e3d83c12a6e2cda2dd951","favicon":"https://dostuffmedia.com/favicon.ico"},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"}],"canonicalUrl":"https://radmin-api-docs.dostuffmedia.com/view/metadata/2sBXwtr9qX"}