Bash/Shell Signature SDK Integration Guide

Overview

The Bash/Shell Signature SDK generates signed request headers such as Authorization and X-Sdk-Date for Meitu Open Platform API requests. The SDK signs the request, and the caller sends it with curl.

Current version: AIGCP-API-shell-sdk-1.0.1.

Requirements

  • Run scripts with Bash. Do not use sh as a substitute.
  • Install cURL 7.76.0 or later.
  • Install openssl, base64, cut, sed, sort, od, tr, and date.
  • Keep the server clock accurate.

Run the following command to check the environment:

for command_name in bash curl openssl base64 cut sed sort od tr date; do
  command -v "$command_name" >/dev/null || printf 'Missing command: %s\n' "$command_name" >&2
done

Download and import

Download AIGCP-API-shell-sdk-1.0.1.zip

unzip AIGCP-API-shell-sdk-1.0.1.zip
cd bash

Use these two files from the extracted archive:

  • signer.sh: signing implementation;
  • demo.sh: basic calling example.

Import signer.sh in the application script:

source ./signer.sh

API reference

The SDK provides the global Sign function:

auth_value=$(Sign "$access_key" "$secret_key" "$url" "$method" "$headers" "$body")
ParameterDescription
access_keyThe application's AK.
secret_keyThe SK paired with the AK.
urlThe final request URL, including its path and complete query.
methodThe uppercase HTTP method, such as GET or POST.
headersA newline-delimited string of Name:Value headers.
bodyThe actual request body; use an empty string when there is no body.

Sign returns a newline-delimited header string. The first line is Authorization; the remaining lines are signed request headers. Convert every line into a separate curl -H argument before sending the request.

Complete POST example

The following example calls the production synchronous task endpoint, https://openapi.meitu.com/api/v1/sdk/sync/push. Its body has five top-level fields: task, task_type, init_images, params, and sync_timeout. The params value must be a JSON string.

Set the task, image, business parameters, and sync_timeout: 30 according to the target capability's API reference. The script uses the same body variable for signing and sending, ensuring that the signed bytes exactly match the transmitted bytes.

#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C

script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
source "$script_dir/signer.sh"

: "${AIGCP_ACCESS_KEY:?AIGCP_ACCESS_KEY is required}"
: "${AIGCP_SECRET_KEY:?AIGCP_SECRET_KEY is required}"

send_signed_request() {
  local method=$1
  local url=$2
  local body=$3
  shift 3

  local raw_headers=("$@")
  local headers
  local auth_value
  local header
  local curl_args

  headers=$(printf '%s\n' "${raw_headers[@]}")
  if ! auth_value=$(Sign "$AIGCP_ACCESS_KEY" "$AIGCP_SECRET_KEY" "$url" "$method" "$headers" "$body"); then
    printf 'Signing failed\n' >&2
    return 1
  fi

  curl_args=(
    --silent
    --show-error
    --fail-with-body
    --connect-timeout 5
    --max-time 60
    --request "$method"
  )
  while IFS= read -r header; do
    [[ -n $header ]] && curl_args+=(-H "$header")
  done <<< "$auth_value"
  [[ -z $body ]] || curl_args+=(--data-binary "$body")

  curl "${curl_args[@]}" "$url"
}

post_endpoint='https://openapi.meitu.com/api/v1/sdk/sync/push'
post_url="${post_endpoint}?"
post_body='{"task":"/v1/replace-with-product-task","task_type":"formula","init_images":[{"url":"https://example.com/input.jpg","profile":{"media_profiles":{"media_data_type":"url"},"version":"v1"}}],"params":"{\"parameter\":{\"rsp_media_type\":\"url\"}}","sync_timeout":30}'
post_headers=(
  "Content-Type:application/json"
  "Host:openapi.meitu.com"
)

send_signed_request 'POST' "$post_url" "$post_body" "${post_headers[@]}"

Save the script as request.sh next to signer.sh, set the AK/SK, and run it:

export AIGCP_ACCESS_KEY='<your-access-key>'
export AIGCP_SECRET_KEY='<your-secret-key>'
bash request.sh

GET example

/api/v1/sdk/sync/push supports POST only. To call another GET API, replace the final POST section of the complete script above with the following code, using the real URL and query parameters from the target API reference:

get_url='https://openapi.meitu.com/api/v1/replace-with-get-path?task_id=replace-with-task-id'
get_body=''
get_headers=(
  "Host:openapi.meitu.com"
)

send_signed_request 'GET' "$get_url" "$get_body" "${get_headers[@]}"

Notes

  • Shell SDK 1.0.1 requires ? to be present in the URL. Retain an empty trailing ? when there is no query; when a query exists, pass it in full. Signing and sending must use the same URL.
  • Finalize the HTTP method, URL, headers, and body before signing. Do not modify them afterward.
  • Generate a JSON body once and pass the same string to both Sign and curl --data-binary.
  • Use Name:Value header format without incidental whitespace before the value. Sort multiple headers by lowercase name.
  • Do not set X-Sdk-Date manually; let the SDK generate it.
  • By default, the SDK calculates SHA-256 over the body. Add X-Sdk-Content-Sha256:UNSIGNED-PAYLOAD only when the target API explicitly supports it.
  • Store the SK only on the server; never include it in frontend or client code.

Common errors

SymptomResolution
Signature verification fails or the API returns 401Check the AK/SK, HTTP method, complete URL, trailing ?, header order, and whether the body exactly matches the signed value.
Time-related errorSynchronize the server clock and remove any manually supplied X-Sdk-Date.
Query signature failureBuild the final query before signing. Do not append, remove, or re-encode parameters afterward.
cURL does not support --fail-with-bodyUpgrade to cURL 7.76.0 or later, or use --fail.
A required command is missingInstall the command listed under Requirements.
The API rejects business parametersReplace the sample task, image, params, task_type, and sync_timeout according to the target capability's API reference.