import Shoply from "@shoplygg/node";
const shoply = new Shoply({ apiKey: process.env.SHOPLY_API_KEY });
const result = await shoply.storefronts.codeSave("STOREFRONT_ID", {
path: "pages/index.liquid",
content: "...",
});<?php
require 'vendor/autoload.php';
$shoply = new Shoply\Client(['apiKey' => getenv('SHOPLY_API_KEY')]);
$result = $shoply->storefronts->codeSave('STOREFRONT_ID', [
'path' => 'pages/index.liquid',
'content' => '...',
]);
import shoply
client = shoply.Client() # reads SHOPLY_API_KEY
result = client.storefronts.codeSave("STOREFRONT_ID", path="pages/index.liquid", content="...")
curl --request PUT \
--url https://api.shoply.gg/v1/stores/{storeId}/storefronts/{storefrontId}/code/file \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"path": "pages/index.liquid",
"content": "<string>",
"was": "<string>"
}
'package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.shoply.gg/v1/stores/{storeId}/storefronts/{storefrontId}/code/file"
payload := strings.NewReader("{\n \"path\": \"pages/index.liquid\",\n \"content\": \"<string>\",\n \"was\": \"<string>\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.shoply.gg/v1/stores/{storeId}/storefronts/{storefrontId}/code/file")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"path\": \"pages/index.liquid\",\n \"content\": \"<string>\",\n \"was\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.shoply.gg/v1/stores/{storeId}/storefronts/{storefrontId}/code/file")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"path\": \"pages/index.liquid\",\n \"content\": \"<string>\",\n \"was\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": null,
"code": null,
"data": {
"file": {
"path": "assets/theme.css",
"hash": "28159614c556580924ad89d6f391cf7584e095c9955d29452fd67c671ebb136b",
"size": 177668,
"added": false,
"changed": true,
"updatedAt": "2026-10-22T16:20:20Z",
"content": "/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties;\n:root, :host {\n --fa-font-solid: normal 900 1em/1 'Font Awesome 7 Free';\n --fa-font-regular: normal 400 1em/1 'Font Awesome 7 Free';\n --fa-font-light: normal 300 1em/1 'Font Awesome 7 Pro';\n --fa-font-thin: normal 100 1em/1 'Font Awesome 7 Pro';\n --fa-font-duotone: normal 900 1em/1 'Font Awesome 7 Duotone';\n …"
},
"rev": 2,
"code": {
"rev": 2,
"ahead": 107,
"designAhead": true,
"base": "2.6.0",
"files": [
{
"path": "assets/theme.css",
"hash": "28159614c556580924ad89d6f391cf7584e095c9955d29452fd67c671ebb136b",
"size": 177668,
"added": false,
"changed": true,
"updatedAt": "2026-10-22T16:20:20Z"
},
{
"path": "assets/theme.js",
"hash": "ff1c708528bdf701288651d9e625dab13517f375460d1b206be9e8243345ccf0",
"size": 144234,
"added": false,
"changed": false,
"updatedAt": "2026-10-22T16:20:20Z"
}
],
"problems": [],
"limits": {
"files": 150,
"fileBytes": 262144,
"bytes": 3145728,
"used": 855369
},
"folders": {
"layout": [
"liquid"
],
"pages": [
"liquid"
],
"elements": [
"liquid"
],
"parts": [
"liquid"
],
"assets": [
"css",
"js"
],
"locales": [
"json"
],
"config": [
"json"
]
}
}
}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}Save a file
Saves a file the draft has. Send was, the hash it had when you read it, and the save is refused with file_conflict if it has changed since (in the code studio, say), with the file as it now stands in file: left out, it is saved whatever happened in between. Saved to the draft only: buyers see it once it is published. Answers the file as it now stands (file) and the whole list again (code), with what is now wrong in the templates. What is written counts toward the store’s hour of saves, as the code studio’s does.
Needs the storefronts.write permission (Change Storefronts).
import Shoply from "@shoplygg/node";
const shoply = new Shoply({ apiKey: process.env.SHOPLY_API_KEY });
const result = await shoply.storefronts.codeSave("STOREFRONT_ID", {
path: "pages/index.liquid",
content: "...",
});<?php
require 'vendor/autoload.php';
$shoply = new Shoply\Client(['apiKey' => getenv('SHOPLY_API_KEY')]);
$result = $shoply->storefronts->codeSave('STOREFRONT_ID', [
'path' => 'pages/index.liquid',
'content' => '...',
]);
import shoply
client = shoply.Client() # reads SHOPLY_API_KEY
result = client.storefronts.codeSave("STOREFRONT_ID", path="pages/index.liquid", content="...")
curl --request PUT \
--url https://api.shoply.gg/v1/stores/{storeId}/storefronts/{storefrontId}/code/file \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"path": "pages/index.liquid",
"content": "<string>",
"was": "<string>"
}
'package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.shoply.gg/v1/stores/{storeId}/storefronts/{storefrontId}/code/file"
payload := strings.NewReader("{\n \"path\": \"pages/index.liquid\",\n \"content\": \"<string>\",\n \"was\": \"<string>\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.shoply.gg/v1/stores/{storeId}/storefronts/{storefrontId}/code/file")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"path\": \"pages/index.liquid\",\n \"content\": \"<string>\",\n \"was\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.shoply.gg/v1/stores/{storeId}/storefronts/{storefrontId}/code/file")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"path\": \"pages/index.liquid\",\n \"content\": \"<string>\",\n \"was\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": null,
"code": null,
"data": {
"file": {
"path": "assets/theme.css",
"hash": "28159614c556580924ad89d6f391cf7584e095c9955d29452fd67c671ebb136b",
"size": 177668,
"added": false,
"changed": true,
"updatedAt": "2026-10-22T16:20:20Z",
"content": "/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties;\n:root, :host {\n --fa-font-solid: normal 900 1em/1 'Font Awesome 7 Free';\n --fa-font-regular: normal 400 1em/1 'Font Awesome 7 Free';\n --fa-font-light: normal 300 1em/1 'Font Awesome 7 Pro';\n --fa-font-thin: normal 100 1em/1 'Font Awesome 7 Pro';\n --fa-font-duotone: normal 900 1em/1 'Font Awesome 7 Duotone';\n …"
},
"rev": 2,
"code": {
"rev": 2,
"ahead": 107,
"designAhead": true,
"base": "2.6.0",
"files": [
{
"path": "assets/theme.css",
"hash": "28159614c556580924ad89d6f391cf7584e095c9955d29452fd67c671ebb136b",
"size": 177668,
"added": false,
"changed": true,
"updatedAt": "2026-10-22T16:20:20Z"
},
{
"path": "assets/theme.js",
"hash": "ff1c708528bdf701288651d9e625dab13517f375460d1b206be9e8243345ccf0",
"size": 144234,
"added": false,
"changed": false,
"updatedAt": "2026-10-22T16:20:20Z"
}
],
"problems": [],
"limits": {
"files": 150,
"fileBytes": 262144,
"bytes": 3145728,
"used": 855369
},
"folders": {
"layout": [
"liquid"
],
"pages": [
"liquid"
],
"elements": [
"liquid"
],
"parts": [
"liquid"
],
"assets": [
"css",
"js"
],
"locales": [
"json"
],
"config": [
"json"
]
}
}
}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}Authorizations
A secret API key, made under Developers in the dashboard: Authorization: Bearer shoply_sk_...
Headers
A word of your own for this one change, up to 180 letters, digits, dots, dashes, underscores and colons. Sent again with the same key, the request is not carried out twice: the first answer comes back, with Idempotent-Replay: true.
Path Parameters
The store's ID. A key reaches the store it was made in: GET /key answers which.
The storefront.

