{
  "info": {
    "name": "ShepCard API",
    "description": "ShepCard API — programmatic access to digital business cards, scan analytics, and webhooks (Enterprise plan).\n\n## Getting started\n\n1. Create an API token: Settings → Developer → API tokens → Create token.\n2. Set the `token` collection variable to your `scp_…` token.\n3. `baseUrl` already points at production (`https://shepcard.com/api/v1`). Set it to `http://localhost:3000/api/v1` to test against a local dev server instead.\n4. Run **Cards → Create a card** first — the `cardId` variable is set automatically from its response.\n\n⚠️ **`baseUrl` targets production by default**, and **Cards → Delete a card** is permanent. Check `cardId` before running it.\n\nSee the interactive docs at https://shepcard.com/docs for the full reference.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    { "key": "baseUrl", "value": "https://shepcard.com/api/v1", "type": "string" },
    { "key": "token", "value": "scp_YOUR_TOKEN_HERE", "type": "string" },
    { "key": "cardId", "value": "", "type": "string" }
  ],
  "auth": {
    "type": "bearer",
    "bearer": [{ "key": "token", "value": "{{token}}", "type": "string" }]
  },
  "item": [
    {
      "name": "Cards",
      "item": [
        {
          "name": "List cards",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/cards",
              "host": ["{{baseUrl}}"],
              "path": ["cards"]
            },
            "description": "Returns all of your cards, newest first. Pass ?archived=true to include archived cards (excluded by default). Requires scope: read."
          }
        },
        {
          "name": "Create a card",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 201', () => pm.response.to.have.status(201));",
                  "const json = pm.response.json();",
                  "if (json.card && json.card.id) {",
                  "  pm.collectionVariables.set('cardId', json.card.id);",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Ada Lovelace — Card\",\n  \"published\": true,\n  \"theme\": { \"palette\": \"ocean\" },\n  \"sections\": [\n    { \"id\": \"sec_1\", \"type\": \"profile\", \"data\": { \"name\": \"Ada Lovelace\", \"title\": \"Mathematician\" } },\n    { \"id\": \"sec_2\", \"type\": \"contact\", \"data\": { \"email\": \"ada@example.com\", \"phone\": \"+233 20 000 0000\" } }\n  ]\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/cards",
              "host": ["{{baseUrl}}"],
              "path": ["cards"]
            },
            "description": "Creates a card. Fires a card.created webhook. The card.id response value is saved to the cardId collection variable automatically. Requires scope: write."
          }
        },
        {
          "name": "Get a card",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/cards/{{cardId}}",
              "host": ["{{baseUrl}}"],
              "path": ["cards", "{{cardId}}"]
            },
            "description": "Gets one card. Non-owned or unknown ids return 404. Requires scope: read."
          }
        },
        {
          "name": "Update a card",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "PUT",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Ada Lovelace — Consulting\",\n  \"seoDescription\": \"Mathematician and writer, available for consulting.\"\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/cards/{{cardId}}",
              "host": ["{{baseUrl}}"],
              "path": ["cards", "{{cardId}}"]
            },
            "description": "Partial update — send only the fields to change. Changing slug to one in use returns 409. Fires a card.updated webhook. Requires scope: write."
          }
        },
        {
          "name": "Delete a card",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/cards/{{cardId}}",
              "host": ["{{baseUrl}}"],
              "path": ["cards", "{{cardId}}"]
            },
            "description": "Permanently deletes a card. Fires a card.deleted webhook. Requires scope: write."
          }
        }
      ]
    },
    {
      "name": "Analytics",
      "item": [
        {
          "name": "Card scan analytics",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 200', () => pm.response.to.have.status(200));"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/cards/{{cardId}}/scans?days=30",
              "host": ["{{baseUrl}}"],
              "path": ["cards", "{{cardId}}", "scans"],
              "query": [{ "key": "days", "value": "30" }]
            },
            "description": "Scan analytics for one card: totals, unique visitors, daily series, device/country breakdowns, and recent scans. days is 1–365 (default 30). Requires scope: analytics."
          }
        }
      ]
    },
    {
      "name": "Webhooks",
      "item": [
        {
          "name": "Register a webhook",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "pm.test('Status 201', () => pm.response.to.have.status(201));",
                  "const json = pm.response.json();",
                  "if (json.webhook) {",
                  "  pm.collectionVariables.set('webhookSecret', json.webhook.secret);",
                  "  pm.collectionVariables.set('webhookId', json.webhook.id);",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"https://example.com/hooks/shepcard\",\n  \"events\": [\"card.created\", \"card.updated\", \"card.deleted\", \"scan.recorded\", \"lead.created\"]\n}",
              "options": { "raw": { "language": "json" } }
            },
            "url": {
              "raw": "{{baseUrl}}/webhooks",
              "host": ["{{baseUrl}}"],
              "path": ["webhooks"]
            },
            "description": "Registers a webhook endpoint. URL must be https://. The signing secret is returned once in this response (also re-revealable in Settings → Developer). Requires scope: write."
          }
        }
      ]
    }
  ]
}
