Order Handoff API

Social Print Studio provides an API endpoint that lets external applications add products to our Shopify cart. Your app sends a simple JSON payload describing what to add, and receives a URL to redirect the customer to. The customer lands on our Shopify cart with the product already added, and can then checkout and pay directly on our website. We handle production, printing, and any customer service.

What you don’t need

What you do need

Endpoint

POSThttps://printkit.dev/api/add-to-cart
text
Content-Type: application/json
Authorization: Bearer <your-api-key>  (optional)

Request Body

Required Fields

FieldTypeDescription
skustringThe Shopify product SKU. Must exactly match a variant SKU in our Shopify store.
sourcestringAn identifier for your application (e.g. "my-app-name"). Used for tracking and debugging.
projectDataobjectProject/order data to persist for fulfillment. All products require this since they are custom printed.

Optional Fields

FieldTypeDefaultDescription
emailstringA contact email address. Highly recommended — allows us to reach out to you if there are any issues with the order.
quantitynumber1How many copies to add to the cart. Must be a positive integer.
propertiesobject{}Extra key-value pairs to attach to the Shopify line item. See Line Item Properties.
checkoutbooleanfalseSkip the cart and send the customer straight to checkout. See Direct Checkout.

Project Data

The projectData object contains the custom content (photos, designs, etc.) that our fulfillment team needs to access when producing the order. When included, the data is saved to our project database and a unique projectId is generated. This ID is automatically attached to the Shopify line item.

FieldTypeDescription
projectData.photosstring[]Array of image URLs. Must be publicly accessible. At least one URL is required.
projectData.metadataobjectAny arbitrary JSON-serializable data you want to persist with the project. Optional in most cases.

Photo URL Requirements

RequirementDetails
FormatsJPG or PNG recommended
Max file size50 MB per image
URL validityMust remain publicly accessible for at least one week after the order is placed

Line Item Properties

The properties object lets you attach key-value string pairs to the Shopify cart line item. These are visible in the Shopify order admin and available to our fulfillment systems.

Example KeyDescription
_project_IdA project ID from your app (hidden from customer). Useful if you need to cross-reference an order later.
_cover_preview_urlA URL shown as the product thumbnail/preview image in the cart (hidden from customer).
Edit Project LinkA URL letting the customer return to your app to edit their project. Visible to the customer.
Project NameAn optional customer-facing name, shown in the cart. Visible to the customer.

Response

Success (200)

json
{
  "success": true,
  "redirectUrl": "https://socialprintstudio.com/pages/newcart?cartKey=prod_1707400000_abc123def",
  "projectId": "65a1b2c3d4e5f6a7b8c9d0e1"
}
FieldTypeDescription
successbooleantrue if the item was staged successfully.
redirectUrlstringThe URL to redirect the customer’s browser to. Single-use — works once, then expires.
projectIdstringThe database ID of the saved project. Store this for your own records if needed.

After receiving the response, redirect the customer’s browser to redirectUrl.

Error Responses

StatusMeaning
400Missing or invalid required field (sku, source, or projectData). Check the error message.
401Invalid API key. Only returned when an Authorization header is provided but the key is not valid. Omitting the header entirely is fine.
405Wrong HTTP method. Use POST.
502SKU could not be resolved to a Shopify product. It likely doesn’t match any variant in our store.
500Internal server error. Contact us if this persists.

All error responses include an error field with a human-readable message:

json
{
  "error": "Missing required field: \"sku\" (string). This should be the Shopify product SKU."
}

Direct Checkout

By default, the redirectUrl sends the customer to the Social Print Studio cart where they can review their order before checking out. If you’d rather skip the cart and send the customer straight to checkout, add "checkout": true to your request body. Everything else stays the same — same endpoint, same fields, same response format. The only difference is where the redirectUrl points.

When to use direct checkout

Direct Checkout Example

curl -X POST https://printkit.dev/api/add-to-cart \
  -H "Content-Type: application/json" \
  -d '{
    "sku": "metal-print-4x4",
    "source": "my-app",
    "email": "[email protected]",
    "checkout": true,
    "projectData": {
      "photos": ["https://cdn.example.com/photo.jpg"]
    }
  }'

Examples

Minimal Example — Simple Photo Product

curl -X POST https://printkit.dev/api/add-to-cart \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "sku": "metal-print-4x4",
    "source": "my-partner-app",
    "email": "[email protected]",
    "projectData": {
      "photos": [
        "https://cdn.example.com/uploads/user123/photo-sunset.jpg"
      ]
    }
  }'

# Response:
# { "success": true, "redirectUrl": "https://...", "projectId": "..." }
# Redirect the customer's browser to redirectUrl

Full Example — Photo Product with Metadata

curl -X POST https://printkit.dev/api/add-to-cart \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "sku": "photo-books-softcover",
    "quantity": 1,
    "source": "my-partner-app",
    "email": "[email protected]",
    "projectData": {
      "photos": [
        "https://cdn.example.com/uploads/user123/cover-file.jpg",
        "https://cdn.example.com/uploads/user123/page-1.jpg",
        "https://cdn.example.com/uploads/user123/page-2.jpg",
        "https://cdn.example.com/uploads/user123/page-3.jpg",
        "https://cdn.example.com/uploads/user123/page-4.jpg",
        "https://cdn.example.com/uploads/user123/page-5.jpg",
        "https://cdn.example.com/uploads/user123/page-38.jpg"
      ],
      "metadata": {
        "bookTitle": "Summer Vacation 2025",
        "customerNotes": "Extra info stored with the order record."
      }
    },
    "properties": {
      "Project Name": "Summer Vacation 2025",
      "_cover_preview_url": "https://cdn.example.com/previews/user123/cover-thumb.jpg"
    }
  }'

Multiple Quantity

curl -X POST https://printkit.dev/api/add-to-cart \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "sku": "photo-print-30x40",
    "quantity": 3,
    "source": "my-partner-app",
    "projectData": {
      "photos": ["https://cdn.example.com/photo1.jpg"]
    }
  }'

SKU Requirements

The sku value must exactly match a product variant SKU in our Shopify store. If the SKU doesn’t match, the API returns a 502 error.

Integration Flow

text
┌─────────────────────┐
│   Your Application  │
│                     │
│  1. User finishes   │
│     creating their  │
│     product         │
│                     │
│  2. POST to         │
│     /api/add-to-cart│
│     with SKU +      │
│     project data    │
└────────┬────────────┘


┌─────────────────────┐
│   Our API Endpoint  │
│                     │
│  3. Saves project   │
│     data to our DB  │
│                     │
│  4. Stages cart     │
│     items           │
│                     │
│  5. Returns         │
│     redirectUrl     │
└────────┬────────────┘


┌─────────────────────┐
│  Your app redirects │
│  the user's browser │
│  to redirectUrl     │
└────────┬────────────┘

    ┌────┴─────┐
    ▼          ▼
┌────────┐ ┌────────────┐
│ Cart   │ │ Checkout   │
│(default│ │(checkout:  │
│ flow)  │ │  true)     │
│        │ │            │
│Customer│ │ Customer   │
│reviews │ │ goes       │
│cart,   │ │ straight   │
│then    │ │ to payment │
│checks  │ │            │
│out     │ │            │
└────────┘ └────────────┘

Important Notes

  1. The redirect URL is single-use. Once the Shopify cart page retrieves the cart data, the key is deleted. Do not attempt to reuse it.
  2. Photo URLs must be publicly accessible. Our fulfillment system downloads these images when producing the order. URLs behind authentication or on localhost will not work. URLs must remain valid for at least one week. If you need simple image hosting, see the Image Upload API.
  3. The source field is important. It helps us track which app generated the order and debug issues. Pick a consistent, descriptive identifier and use it on every request.
  4. CORS is enabled. You can call this endpoint from client-side JavaScript. If you call from a backend server, make sure you pass the redirect URL to the customer’s browser for the final redirect step.
  5. Request size limit is 10 MB. If you’re including many photo URLs or large metadata objects, keep the total payload under 10 MB.
  6. The projectId in the response is the database reference for the saved project. Store this in your own system if you may need to reference it later for debugging or support.